diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 640896e7f..ee90e1be9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,5 +1,6 @@
# Credits to @Scighost from Starward for his contributions!
name: Build-Canary
+run-name: Canary Build for ${{ github.ref }}
on:
workflow_dispatch:
@@ -22,10 +23,7 @@ on:
- "net7.0-windows10.0.22000.0"
- "net7.0-windows10.0.19041.0"
-
-
jobs:
-
build:
runs-on: ${{ github.event.inputs.os }}
strategy:
@@ -36,6 +34,7 @@ jobs:
env:
Configuration: ${{ matrix.configuration }}
Platform: ${{ matrix.platform }}
+ DOTNET_INSTALL_DIR: '.\.dotnet'
steps:
- name: Checkout
@@ -43,6 +42,28 @@ jobs:
with:
submodules: recursive
+ - name: Get short Git SHA
+ id: vars
+ run: |
+ echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
+ echo "branch=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV
+
+ - name: Cache dotnet # cache dotnet install https://stackoverflow.com/questions/75180149/how-to-cache-dotnet-installation-in-github-actions
+ id: cache-dotnet
+ uses: actions/cache@v3
+ with:
+ path: ${{ env.DOTNET_INSTALL_DIR }}
+ key: ${{ runner.os }}-dotnet-7
+ restore-keys: ${{ runner.os }}-dotnet-7
+
+ - name: Cache nuget # cache nuget https://github.com/actions/cache/blob/main/examples.md#c---nuget
+ uses: actions/cache@v3
+ with:
+ path: ~/.nuget/packages
+ key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-nuget-
+
- name: Install .NET
uses: actions/setup-dotnet@v3
with:
@@ -59,16 +80,16 @@ jobs:
msbuild CollapseLauncher "-property:Configuration=$env:Configuration;Platform=$env:Platform"
dotnet build CollapseLauncher -c $env:Configuration -p:Platform=$env:Platform -f ${{ github.event.inputs.framework }}
- - name: Upload Artifact (Debug)
- uses: actions/upload-artifact@v3.1.2
- if: ${{ matrix.configuration == 'Debug' }}
- with:
- name: collapse_${{ github.sha }}.${{ matrix.platform }}-${{ matrix.configuration }}
- path: ./CollapseLauncher/bin/x64/Debug/net7.0-windows10.0.22000.0/
+# - name: Upload Artifact (Debug)
+# uses: actions/upload-artifact@v3.1.2
+# if: ${{ matrix.configuration == 'Debug' }}
+# with:
+# name: collapse_${{ github.ref }}_${{ steps.vars.outputs.sha_short }}.${{ matrix.platform }}-${{ matrix.configuration }}
+# path: ./CollapseLauncher/bin/x64/Debug/${{ github.event.inputs.framework }}/
- name: Upload Artifact (Release)
uses: actions/upload-artifact@v3.1.2
if: ${{ matrix.configuration == 'Release' }}
with:
- name: collapse_${{ github.sha }}.${{ matrix.platform }}-${{ matrix.configuration }}
- path: ./CollapseLauncher/bin/x64/Release/net7.0-windows10.0.22000.0/
+ name: collapse_${{ matrix.platform }}-${{ matrix.configuration }}_${{ github.event.inputs.framework }}_${{ github.sha }}
+ path: ./CollapseLauncher/bin/x64/Release/${{ github.event.inputs.framework }}/
diff --git a/.gitignore b/.gitignore
index ec67c6883..0b7076548 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,83 @@ CollapseLauncher/Invoker/*
*.psd
InstallerProp/Output/*
InstallerProp/temp/**
+
+### Rider ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+.idea/*
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# SonarLint plugin
+.idea/sonarlint/
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..c2414dd4f
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+ overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+dev.kemalsetyaa@gmail.com.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a4aec7264..afd949ce3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,10 +16,17 @@ If you wish to add new language that isn't yet listed in the Crowdin project, pl
## Tools Needed
Below is a list of tools needed to contribute to this project:
1. **Visual Studio 2022 (Any Edition - 17.4 or later)**
+ - Select .NET desktop development component
2. **Windows SDK (10.0.19043.0 or 10.0.22000.0 ONLY)** via Visual Studio Installer
3. .NET Core 7 SDK: [**(7.0.100 or later)**](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)
4. WinUI 3: [**(WindowsAppSDK 1.3.0-230331000 Stable Runtime)**](https://aka.ms/windowsappsdk/1.3/1.3.230331000/windowsappruntimeinstall-x64.exe)
+> **Note**:
+>
+> Starting from November 13rd 2022, you must have Visual Studio 2022 installed on your computer due to the updated minimum system requirement of `WinUI 3 1.3 Stable`.
+>
+> Using a lower Visual Studio version (like VS2019) is possible, but it is not recommended as you need to downgrade **WindowsAppSDK** via *NuGet* to **WindowsAppSDK 1.1.5** or **WindowsAppSDK 1.2-preview2** before building. This has an increased risk of breaking the application and as such, no support will be provided for this method. **This is not recommended for beginner users.**
+
## Restrictions for New Feature(s)
While this software is fully open source and not affiliated with HoYoverse, Cognosphere, or any of its related entities in any way, we are nonetheless bound to their Terms of Service and Code of Conduct when developing Collapse. This means that there are some features that we will **not** implement. We will close any issue or PRs that are made to add such functionality to Collapse. Such features include, but are not limited to:
- Anything that, in any way, interacts with the miHoYo SDK and/or API, including their Authentication and Payment Processing endpoints.
diff --git a/CollapseLauncher/App.xaml b/CollapseLauncher/App.xaml
index 6749198c0..771d2735b 100644
--- a/CollapseLauncher/App.xaml
+++ b/CollapseLauncher/App.xaml
@@ -2,7 +2,8 @@
x:Class="CollapseLauncher.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:local="using:CollapseLauncher">
+ xmlns:local="using:CollapseLauncher"
+ xmlns:localUI="using:Microsoft.UI.Xaml.Controls">
@@ -14,7 +15,7 @@
#ffd52a
#ffd52a
#ffd52a
-
+
@@ -46,21 +47,23 @@
-
+
-
-
+
+
+
+
-
-
-
+
+
+
@@ -98,7 +101,7 @@
-
+
@@ -107,21 +110,307 @@
-
+
+
-
+
+
+ ms-appx:///Assets/Fonts/FontAwesomeBrand6.otf#Font Awesome 6 Brands
+ ms-appx:///Assets/Fonts/FontAwesomeRegular6.otf#Font Awesome 6 Free
+ ms-appx:///Assets/Fonts/FontAwesomeSolid6.otf#Font Awesome 6 Free Solid
+ 0,47,0,0
+
+
+
+
+
+
-
- ms-appx:///Assets/Fonts/FontAwesomeBrand6.otf#Font Awesome 6 Brands
- ms-appx:///Assets/Fonts/FontAwesomeRegular6.otf#Font Awesome 6 Free
- ms-appx:///Assets/Fonts/FontAwesomeSolid6.otf#Font Awesome 6 Free Solid
-
diff --git a/CollapseLauncher/App.xaml.cs b/CollapseLauncher/App.xaml.cs
index 215452493..9c7436936 100644
--- a/CollapseLauncher/App.xaml.cs
+++ b/CollapseLauncher/App.xaml.cs
@@ -1,6 +1,14 @@
using Hi3Helper;
+using Hi3Helper.Shared.Region;
+using Microsoft.UI;
using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Resources;
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.Storage;
using static CollapseLauncher.InnerLauncherConfig;
using static Hi3Helper.Logger;
@@ -15,6 +23,10 @@ public App()
{
try
{
+ bool IsAcrylicEnabled = LauncherConfig.GetAppConfigValue("EnableAcrylicEffect").ToBool();
+
+ if (!IsAcrylicEnabled) ToggleBlurBackdrop(false);
+
this.InitializeComponent();
RequestedTheme = CurrentRequestedAppTheme = GetAppTheme();
@@ -39,5 +51,45 @@ public App()
Console.ReadLine();
}
}
+
+ public static async void ToggleBlurBackdrop(bool useBackdrop = true)
+ {
+ // Always wait for the resources to load up
+ while (true)
+ {
+ try
+ {
+ await Task.Delay(250);
+ if (Current.Resources.Count != 0) break;
+ }
+ catch { }
+ }
+
+ // Enumerate the dictionary (MergedDictionaries)
+ foreach (ResourceDictionary resource in Current
+ .Resources
+ .MergedDictionaries)
+ {
+ // Parse the dictionary (ThemeDictionaries) and read the type of KeyValuePair,
+ // then select the value, get the type of ResourceDictionary, then enumerate it
+ foreach (ResourceDictionary list in resource
+ .ThemeDictionaries
+ .OfType>()
+ .Select(x => x.Value)
+ .OfType())
+ {
+ // Parse the dictionary as type of KeyValuePair,
+ // and get the value which has type of AcrylicBrush only, then enumerate it
+ foreach (AcrylicBrush theme in list
+ .OfType>()
+ .Select(x => x.Value)
+ .OfType())
+ {
+ // Set the theme AlwaysUseFallback as per toggle from useBackdrop.
+ theme.AlwaysUseFallback = !useBackdrop;
+ }
+ }
+ }
+ }
}
}
diff --git a/CollapseLauncher/Assets/BG/AiHappy.png b/CollapseLauncher/Assets/Images/AiHappy.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/AiHappy.png
rename to CollapseLauncher/Assets/Images/AiHappy.png
diff --git a/CollapseLauncher/Assets/BG/AponiaFly.png b/CollapseLauncher/Assets/Images/AponiaFly.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/AponiaFly.png
rename to CollapseLauncher/Assets/Images/AponiaFly.png
diff --git a/CollapseLauncher/Assets/BG/PaimonSleep.png b/CollapseLauncher/Assets/Images/PaimonSleep.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/PaimonSleep.png
rename to CollapseLauncher/Assets/Images/PaimonSleep.png
diff --git a/CollapseLauncher/Assets/BG/PaimonWhat.png b/CollapseLauncher/Assets/Images/PaimonWhat.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/PaimonWhat.png
rename to CollapseLauncher/Assets/Images/PaimonWhat.png
diff --git a/CollapseLauncher/Assets/BG/StartUpBG.png b/CollapseLauncher/Assets/Images/StartupBackground.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/StartUpBG.png
rename to CollapseLauncher/Assets/Images/StartupBackground.png
diff --git a/CollapseLauncher/Assets/BG/StartUpBG2.png b/CollapseLauncher/Assets/Images/StartupBackground2.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/StartUpBG2.png
rename to CollapseLauncher/Assets/Images/StartupBackground2.png
diff --git a/CollapseLauncher/Assets/BG/default.png b/CollapseLauncher/Assets/Images/default.png
similarity index 100%
rename from CollapseLauncher/Assets/BG/default.png
rename to CollapseLauncher/Assets/Images/default.png
diff --git a/CollapseLauncher/Assets/Presets/CommunityTools.json b/CollapseLauncher/Assets/Presets/CommunityTools.json
index 1e794d1cd..3d225e8dd 100644
--- a/CollapseLauncher/Assets/Presets/CommunityTools.json
+++ b/CollapseLauncher/Assets/Presets/CommunityTools.json
@@ -80,6 +80,12 @@
"IconGlyph": "",
"Text": "Reddit Community",
"URL": "https://www.reddit.com/r/HonkaiImpact3rd/"
+ },
+ {
+ "IconFontFamily": "ms-appx:///Assets/Fonts/FontAwesomeSolid6.otf#Font Awesome 6 Free Solid",
+ "IconGlyph": "",
+ "Text": "ER Build Guide",
+ "URL": "https://risbi0.github.io/Elysian-Realm/"
}
],
"Genshin": [
@@ -159,4 +165,4 @@
}
]
}
-}
\ No newline at end of file
+}
diff --git a/CollapseLauncher/Classes/BackgroundManagement/BackgroundManagement.cs b/CollapseLauncher/Classes/BackgroundManagement/BackgroundManagement.cs
index 8222c81c4..050db1284 100644
--- a/CollapseLauncher/Classes/BackgroundManagement/BackgroundManagement.cs
+++ b/CollapseLauncher/Classes/BackgroundManagement/BackgroundManagement.cs
@@ -1,7 +1,6 @@
using ColorThiefDotNet;
using Hi3Helper;
using Hi3Helper.Data;
-using Hi3Helper.Preset;
using Hi3Helper.Shared.ClassStruct;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -13,13 +12,10 @@
using System.Drawing;
using System.IO;
using System.Linq;
-using System.Text.Json;
-using System.Threading;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using static CollapseLauncher.InnerLauncherConfig;
-using static Hi3Helper.Locale;
using static Hi3Helper.Logger;
using static Hi3Helper.Shared.Region.LauncherConfig;
@@ -34,20 +30,6 @@ public sealed partial class MainPage : Page
private bool BGLastState = true;
private bool IsFirstStartup = true;
- private async ValueTask FetchLauncherLocalizedResources(CancellationToken Token, PresetConfigV2 Preset)
- {
- regionBackgroundProp = Preset.LauncherSpriteURLMultiLang ?
- await TryGetMultiLangResourceProp(Token, Preset) :
- await TryGetSingleLangResourceProp(Token, Preset);
-
- await DownloadBackgroundImage(Token);
-
- await GetLauncherAdvInfo(Token, Preset);
- await GetLauncherCarouselInfo(Token);
- await GetLauncherEventInfo(Token);
- GetLauncherPostInfo();
- }
-
private async Task ChangeBackgroundImageAsRegion()
{
IsCustomBG = GetAppConfigValue("UseCustomBG").ToBool();
@@ -70,236 +52,124 @@ private async Task ChangeBackgroundImageAsRegion()
ReloadPageTheme(this, ConvertAppThemeToElementTheme(CurrentAppTheme));
}
- private async ValueTask FetchLauncherDownloadInformation(CancellationToken Token, PresetConfigV2 Preset)
- {
- using (Stream netStream = (await _httpClient.DownloadFromSessionStreamAsync(
- Preset.LauncherResourceURL,
- 0,
- null,
- Token
- )).Item1)
- {
- _gameAPIProp = (RegionResourceProp)JsonSerializer.Deserialize(netStream, typeof(RegionResourceProp), RegionResourcePropContext.Default) ?? new RegionResourceProp();
-
-#if DEBUG
- if (_gameAPIProp.data.game.latest.decompressed_path != null) LogWriteLine($"Decompressed Path: {_gameAPIProp.data.game.latest.decompressed_path}", LogType.Default, true);
- if (_gameAPIProp.data.game.latest.path != null) LogWriteLine($"ZIP Path: {_gameAPIProp.data.game.latest.path}", LogType.Default, true);
- if (_gameAPIProp.data.pre_download_game?.latest?.decompressed_path != null) LogWriteLine($"Decompressed Path Pre-load: {_gameAPIProp.data.pre_download_game?.latest?.decompressed_path}", LogType.Default, true);
- if (_gameAPIProp.data.pre_download_game?.latest?.path != null) LogWriteLine($"ZIP Path Pre-load: {_gameAPIProp.data.pre_download_game?.latest?.path}", LogType.Default, true);
-#endif
- }
- }
-
- private async ValueTask TryGetMultiLangResourceProp(CancellationToken Token, PresetConfigV2 Preset)
- {
- RegionResourceProp ret = await GetMultiLangResourceProp(Lang.LanguageID.ToLower(), Token, Preset);
-
- return ret.data.adv == null
- || ((ret.data.adv.version ?? 5) <= 4
- && Preset.GameType == GameType.Honkai) ?
- await GetMultiLangResourceProp(Preset.LauncherSpriteURLMultiLangFallback ?? "en-us", Token, Preset) :
- ret;
- }
-
- private async ValueTask GetMultiLangResourceProp(string langID, CancellationToken token, PresetConfigV2 Preset)
- {
- using (Stream netStream = (await _httpClient.DownloadFromSessionStreamAsync(
- string.Format(Preset.LauncherSpriteURL, langID),
- 0,
- null,
- token
- )).Item1)
- {
- return (RegionResourceProp)JsonSerializer.Deserialize(netStream, typeof(RegionResourceProp), RegionResourcePropContext.Default) ?? new RegionResourceProp();
- }
- }
-
- private async ValueTask TryGetSingleLangResourceProp(CancellationToken Token, PresetConfigV2 Preset)
- {
- using (Stream netStream = (await _httpClient.DownloadFromSessionStreamAsync(
- Preset.LauncherSpriteURL,
- 0,
- null,
- Token
- )).Item1)
- {
- return (RegionResourceProp)JsonSerializer.Deserialize(netStream, typeof(RegionResourceProp), RegionResourcePropContext.Default) ?? new RegionResourceProp();
- }
- }
-
- private void ResetRegionProp()
- {
- LastRegionNewsProp = regionNewsProp.Copy();
- regionNewsProp = new HomeMenuPanel()
- {
- sideMenuPanel = null,
- imageCarouselPanel = null,
- articlePanel = null,
- eventPanel = null
- };
- }
-
- private async ValueTask GetLauncherAdvInfo(CancellationToken Token, PresetConfigV2 Preset)
- {
- if (regionBackgroundProp.data.icon.Count == 0) return;
-
- regionNewsProp.sideMenuPanel = new List();
- foreach (RegionSocMedProp item in regionBackgroundProp.data.icon)
- {
- regionNewsProp.sideMenuPanel.Add(new MenuPanelProp
- {
- URL = item.url,
- Icon = await GetCachedSprites(item.img, Token),
- IconHover = await GetCachedSprites(item.img_hover, Token),
- QR = string.IsNullOrEmpty(item.qr_img) ? null : await GetCachedSprites(item.qr_img, Token),
- QR_Description = string.IsNullOrEmpty(item.qr_desc) ? null : item.qr_desc,
- Description = string.IsNullOrEmpty(item.title) || Preset.IsHideSocMedDesc ? item.url : item.title
- });
- }
- }
-
- private async ValueTask GetLauncherCarouselInfo(CancellationToken Token)
+ public static async void ApplyAccentColor(Page page, Bitmap bitmapinput)
{
- if (regionBackgroundProp.data.banner.Count == 0) return;
-
- regionNewsProp.imageCarouselPanel = new List();
- foreach (RegionSocMedProp item in regionBackgroundProp.data.banner)
- {
- regionNewsProp.imageCarouselPanel.Add(new MenuPanelProp
- {
- URL = item.url,
- Icon = await GetCachedSprites(item.img, Token),
- Description = string.IsNullOrEmpty(item.name) ? item.url : item.name
- });
- }
- }
-
- private async ValueTask GetLauncherEventInfo(CancellationToken Token)
- {
- if (string.IsNullOrEmpty(regionBackgroundProp.data.adv.icon)) return;
-
- regionNewsProp.eventPanel = new RegionBackgroundProp
- {
- url = regionBackgroundProp.data.adv.url,
- icon = await GetCachedSprites(regionBackgroundProp.data.adv.icon, Token)
- };
- }
-
- private void GetLauncherPostInfo()
- {
- if (regionBackgroundProp.data.post.Count == 0) return;
-
- regionNewsProp.articlePanel = new PostCarouselTypes();
- foreach (RegionSocMedProp item in regionBackgroundProp.data.post)
- {
- switch (item.type)
- {
- case PostCarouselType.POST_TYPE_ACTIVITY:
- regionNewsProp.articlePanel.Events.Add(item);
- break;
- case PostCarouselType.POST_TYPE_ANNOUNCE:
- regionNewsProp.articlePanel.Notices.Add(item);
- break;
- case PostCarouselType.POST_TYPE_INFO:
- regionNewsProp.articlePanel.Info.Add(item);
- break;
- }
- }
- }
-
- public async ValueTask GetCachedSprites(string URL, CancellationToken token)
- {
- string cacheFolder = Path.Combine(AppGameImgFolder, "cache");
- string cachePath = Path.Combine(cacheFolder, Path.GetFileNameWithoutExtension(URL));
- if (!Directory.Exists(cacheFolder))
- Directory.CreateDirectory(cacheFolder);
-
- FileInfo fInfo = new FileInfo(cachePath);
-
- if (!fInfo.Exists || fInfo.Length < (1 << 10))
- {
- using (FileStream fs = fInfo.Create())
- {
- using (Stream netStream = (await _httpClient.DownloadFromSessionStreamAsync(URL, 0, null, token)).Item1)
- {
- netStream.CopyTo(fs);
- }
- }
- }
-
- return cachePath;
- }
-
- public static async Task ApplyAccentColor(Page page, Bitmap bitmapinput, int quality)
- {
- Windows.UI.Color[] _colors;
switch (CurrentAppTheme)
{
case AppThemeMode.Light:
- _colors = await SetLightColors(bitmapinput, quality);
+ await SetLightColors(bitmapinput);
break;
case AppThemeMode.Dark:
- _colors = await SetDarkColors(bitmapinput, quality);
+ await SetDarkColors(bitmapinput);
break;
default:
if (SystemAppTheme.ToString() == "#FFFFFFFF")
- _colors = await SetLightColors(bitmapinput, quality);
+ await SetLightColors(bitmapinput);
else
- _colors = await SetDarkColors(bitmapinput, quality);
+ await SetDarkColors(bitmapinput);
break;
}
ReloadPageTheme(page, ConvertAppThemeToElementTheme(CurrentAppTheme));
- return _colors;
}
- private static async Task SetLightColors(Bitmap bitmapinput, int quality)
+ private static async Task SetLightColors(Bitmap bitmapinput)
{
- Windows.UI.Color[] _colors = await GetPaletteList(bitmapinput, 128, true, quality);
+ Windows.UI.Color[] _colors = await GetPaletteList(bitmapinput, 10, true, 1);
Application.Current.Resources["SystemAccentColor"] = _colors[0];
- Application.Current.Resources["SystemAccentColorDark1"] = _colors[1];
- Application.Current.Resources["SystemAccentColorDark2"] = _colors[2];
- Application.Current.Resources["SystemAccentColorDark3"] = _colors[3];
- Application.Current.Resources["AccentColor"] = new SolidColorBrush(_colors[0]);
-
- return _colors;
+ Application.Current.Resources["SystemAccentColorDark1"] = _colors[0];
+ Application.Current.Resources["SystemAccentColorDark2"] = _colors[1];
+ Application.Current.Resources["SystemAccentColorDark3"] = _colors[1];
+ Application.Current.Resources["AccentColor"] = new SolidColorBrush(_colors[1]);
}
- private static async Task SetDarkColors(Bitmap bitmapinput, int quality)
+ private static async Task SetDarkColors(Bitmap bitmapinput)
{
- Windows.UI.Color[] _colors = await GetPaletteList(bitmapinput, 255, false, quality);
+ Windows.UI.Color[] _colors = await GetPaletteList(bitmapinput, 10, false, 1);
Application.Current.Resources["SystemAccentColor"] = _colors[0];
- Application.Current.Resources["SystemAccentColorLight1"] = _colors[1];
- Application.Current.Resources["SystemAccentColorLight2"] = _colors[2];
- Application.Current.Resources["SystemAccentColorLight3"] = _colors[3];
+ Application.Current.Resources["SystemAccentColorLight1"] = _colors[0];
+ Application.Current.Resources["SystemAccentColorLight2"] = _colors[1];
+ Application.Current.Resources["SystemAccentColorLight3"] = _colors[0];
Application.Current.Resources["AccentColor"] = new SolidColorBrush(_colors[0]);
-
- return _colors;
}
+
+ private static List _generatedColors = new List();
private static async Task GetPaletteList(Bitmap bitmapinput, int ColorCount, bool IsLight, int quality)
{
byte DefVal = (byte)(IsLight ? 80 : 255);
- Windows.UI.Color[] output = new Windows.UI.Color[4];
try
{
- List ThemedColors = await Task.Run(() => ColorThief.GetPalette(bitmapinput, ColorCount, IsLight ? 1 : quality).Where(x => IsLight ? x.IsDark : !x.IsDark).ToList());
+ LumaUtils.DarkThreshold = IsLight ? 200f : 400f;
+ LumaUtils.IgnoreWhiteThreshold = IsLight ? 900f : 800f;
+ if (!IsLight)
+ LumaUtils.ChangeCoeToBT709();
+ else
+ LumaUtils.ChangeCoeToBT601();
- if (ThemedColors.Count == 0 || ThemedColors.Count < output.Length) throw new Exception($"The image doesn't have {output.Length} matched colors to assign. Fallback to default!");
- for (int i = 0, j = output.Length - 1; i < output.Length; i++, j--)
+ return await Task.Run(() =>
{
- output[i] = DrawingColorToColor(ThemedColors[i]);
- }
+ _generatedColors.Clear();
+
+ while (true)
+ {
+ try
+ {
+ IEnumerable averageColors = ColorThief.GetPalette(bitmapinput, ColorCount, quality, !IsLight)
+ .Where(x => IsLight ? x.IsDark : !x.IsDark)
+ .OrderBy(x => x.Population);
+
+ QuantizedColor dominatedColor = new QuantizedColor(
+ Color.FromArgb(
+ 255,
+ (byte)averageColors.Average(a => a.Color.R),
+ (byte)averageColors.Average(a => a.Color.G),
+ (byte)averageColors.Average(a => a.Color.B)
+ ), (int)averageColors.Average(a => a.Population));
+
+ _generatedColors.Add(dominatedColor);
+ _generatedColors.AddRange(averageColors);
+
+ break;
+ }
+ catch (InvalidOperationException)
+ {
+ if (ColorCount > 100) throw;
+ LogWriteLine($"Regenerating colors by adding 20 more colors to generate: {ColorCount} to {ColorCount + 20}", LogType.Warning, true);
+ ColorCount += 20;
+ }
+ }
+
+ return EnsureLengthCopyLast(_generatedColors
+ .Select(DrawingColorToColor)
+ .ToArray(), 2);
+ }).ConfigureAwait(false);
}
catch (Exception ex)
{
LogWriteLine($"{ex}", LogType.Warning, true);
- Windows.UI.Color defColor = DrawingColorToColor(new QuantizedColor(Color.FromArgb(255, DefVal, DefVal, DefVal), 1));
- return new Windows.UI.Color[] { defColor, defColor, defColor, defColor };
}
- return output;
+ Windows.UI.Color defColor = DrawingColorToColor(new QuantizedColor(Color.FromArgb(255, DefVal, DefVal, DefVal), 1));
+ return new Windows.UI.Color[] { defColor, defColor, defColor, defColor };
+ }
+
+ private static T[] EnsureLengthCopyLast(T[] array, int toLength)
+ {
+ if (array.Length == 0) throw new IndexOutOfRangeException("Array has no content in it");
+ if (array.Length >= toLength) return array;
+
+ T lastArray = array[array.Length - 1];
+ T[] newArray = new T[toLength];
+ Array.Copy(array, newArray, array.Length);
+
+ for (int i = array.Length; i < newArray.Length; i++)
+ {
+ newArray[i] = lastArray;
+ }
+
+ return newArray;
}
private static Windows.UI.Color DrawingColorToColor(QuantizedColor i) => new Windows.UI.Color { R = i.Color.R, G = i.Color.G, B = i.Color.B, A = i.Color.A };
@@ -316,25 +186,21 @@ public async ValueTask GetCachedSprites(string URL, CancellationToken to
FileInfo cachedFileInfo = new FileInfo(cachedFilePath);
- bool isCachedFileExist = cachedFileInfo.Exists && cachedFileInfo.Length > 4 << 15;
- FileStream cachedFileStream = isCachedFileExist ? cachedFileInfo.OpenRead() : cachedFileInfo.Create();
-
- try
+ bool isCachedFileExist = cachedFileInfo.Exists && cachedFileInfo.Length > 1 << 15;
+ using (stream)
+ using (FileStream cachedFileStream = isCachedFileExist ? cachedFileInfo.OpenRead() : cachedFileInfo.Create())
{
- if (!isCachedFileExist)
+ try
{
- await GetResizedImageStream(stream, cachedFileStream, ToWidth, ToHeight);
- }
+ if (!isCachedFileExist)
+ {
+ await GetResizedImageStream(stream, cachedFileStream, ToWidth, ToHeight);
+ }
- bitmapRet = await Task.Run(() => Stream2Bitmap(cachedFileStream.AsRandomAccessStream()));
- bitmapImageRet = await Stream2BitmapImage(cachedFileStream.AsRandomAccessStream());
- }
- catch { throw; }
- finally
- {
- stream?.Dispose();
- cachedFileStream?.Dispose();
- GC.Collect();
+ bitmapRet = await Task.Run(() => Stream2Bitmap(cachedFileStream.AsRandomAccessStream()));
+ bitmapImageRet = await Stream2BitmapImage(cachedFileStream.AsRandomAccessStream());
+ }
+ catch { throw; }
}
return (bitmapRet, bitmapImageRet);
@@ -421,27 +287,6 @@ private static (uint, uint) GetPreservedImageRatio(uint canvasWidth, uint canvas
return ((uint)(imgWidth * ratio), (uint)(imgHeight * ratio));
}
- private async ValueTask DownloadBackgroundImage(CancellationToken Token)
- {
- regionBackgroundProp.imgLocalPath = Path.Combine(AppGameImgFolder, "bg", Path.GetFileName(regionBackgroundProp.data.adv.background));
- SetAndSaveConfigValue("CurrentBackground", regionBackgroundProp.imgLocalPath);
-
- if (!Directory.Exists(Path.Combine(AppGameImgFolder, "bg")))
- Directory.CreateDirectory(Path.Combine(AppGameImgFolder, "bg"));
-
- FileInfo fI = new FileInfo(regionBackgroundProp.imgLocalPath);
-
- if (fI.Exists) return;
-
- using (Stream netStream = (await _httpClient.DownloadFromSessionStreamAsync(regionBackgroundProp.data.adv.background, 0, null, Token)).Item1)
- {
- using (Stream outStream = fI.Create())
- {
- netStream.CopyTo(outStream);
- }
- }
- }
-
private async void ApplyBackgroundAsync() => await ApplyBackground();
private async Task ApplyBackground()
@@ -455,15 +300,10 @@ private async Task ApplyBackground()
(PaletteBitmap, BackgroundBitmap) = await GetResizedBitmap(stream, Width, Height);
- await ApplyAccentColor(this, PaletteBitmap, 7);
+ ApplyAccentColor(this, PaletteBitmap);
FadeOutFrontBg();
FadeOutBackBg();
-
- GC.Collect();
- GC.WaitForPendingFinalizers();
- GC.WaitForFullGCComplete();
- GC.Collect();
}
private async void FadeOutFrontBg()
diff --git a/CollapseLauncher/Classes/CachesManagement/Honkai/Fetch.cs b/CollapseLauncher/Classes/CachesManagement/Honkai/Fetch.cs
index 0024fa30d..752acfec2 100644
--- a/CollapseLauncher/Classes/CachesManagement/Honkai/Fetch.cs
+++ b/CollapseLauncher/Classes/CachesManagement/Honkai/Fetch.cs
@@ -1,4 +1,4 @@
-using CollapseLauncher.Interfaces;
+using CollapseLauncher.Interfaces;
using Hi3Helper;
using Hi3Helper.EncTool;
using Hi3Helper.EncTool.Parser.KianaDispatch;
@@ -82,23 +82,23 @@ private async Task BuildGameRepoURL(CancellationToken token)
KianaDispatch dispatch = null;
Exception lastException = null;
- foreach (string baseURL in _gamePreset.GameDispatchArrayURL)
+ foreach (string baseURL in _gameVersionManager.GamePreset.GameDispatchArrayURL)
{
try
{
// Init the key and decrypt it if exist.
string key = null;
- if (_gamePreset.DispatcherKey != null)
+ if (_gameVersionManager.GamePreset.DispatcherKey != null)
{
mhyEncTool Decryptor = new mhyEncTool();
Decryptor.InitMasterKey(ConfigV2.MasterKey, ConfigV2.MasterKeyBitLength, RSAEncryptionPadding.Pkcs1);
- key = _gamePreset.DispatcherKey;
+ key = _gameVersionManager.GamePreset.DispatcherKey;
Decryptor.DecryptStringWithMasterKey(ref key);
}
// Try assign dispatcher
- dispatch = await KianaDispatch.GetDispatch(baseURL, _gamePreset.GameDispatchURLTemplate, _gamePreset.GameDispatchChannelName, key, _gameVersion.VersionArray, token);
+ dispatch = await KianaDispatch.GetDispatch(baseURL, _gameVersionManager.GamePreset.GameDispatchURLTemplate, _gameVersionManager.GamePreset.GameDispatchChannelName, key, _gameVersion.VersionArray, token);
lastException = null;
break;
}
@@ -112,7 +112,7 @@ private async Task BuildGameRepoURL(CancellationToken token)
if (lastException != null) throw lastException;
// Get gatewayURl and fetch the gateway
- _gameGateway = await KianaDispatch.GetGameserver(dispatch, _gamePreset.GameGatewayDefault, token);
+ _gameGateway = await KianaDispatch.GetGameserver(dispatch, _gameVersionManager.GamePreset.GameGatewayDefault, token);
_gameRepoURL = BuildAssetBundleURL(_gameGateway);
}
@@ -213,7 +213,7 @@ private void BuildDataPatchConfig(MemoryStream stream, List assetInd
try
{
// Deserialize the line and set the type
- CacheAsset content = (CacheAsset)JsonSerializer.Deserialize(line, typeof(CacheAsset), CacheAssetContext.Default);
+ CacheAsset content = (CacheAsset)JsonSerializer.Deserialize(line, typeof(CacheAsset), InternalAppJSONContext.Default);
content.DataType = type;
// Check if the asset is regional and contains only selected language.
diff --git a/CollapseLauncher/Classes/CachesManagement/Honkai/HonkaiCache.cs b/CollapseLauncher/Classes/CachesManagement/Honkai/HonkaiCache.cs
index 621135aa7..8f4b131c7 100644
--- a/CollapseLauncher/Classes/CachesManagement/Honkai/HonkaiCache.cs
+++ b/CollapseLauncher/Classes/CachesManagement/Honkai/HonkaiCache.cs
@@ -2,6 +2,7 @@
using CollapseLauncher.Statics;
using Hi3Helper.Data;
using Hi3Helper.EncTool.Parser.KianaDispatch;
+using Hi3Helper.Preset;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
@@ -20,14 +21,15 @@ internal partial class HonkaiCache : ProgressBase, I
private List _updateAssetIndex { get; set; }
#endregion
- public HonkaiCache(UIElement parentUI)
+ public HonkaiCache(UIElement parentUI, IGameVersionCheck GameVersionManager)
: base(
parentUI,
- PageStatics._GameVersion.GameDirAppDataPath,
+ GameVersionManager,
+ GameVersionManager.GameDirAppDataPath,
null,
- PageStatics._GameVersion.GetGameVersionAPI().VersionString)
+ GameVersionManager.GetGameVersionAPI().VersionString)
{
- _gameLang = _gamePreset.GetGameLanguage() ?? "en";
+ _gameLang = _gameVersionManager.GamePreset.GetGameLanguage() ?? "en";
}
~HonkaiCache() => Dispose();
diff --git a/CollapseLauncher/Classes/CachesManagement/StarRail/Check.cs b/CollapseLauncher/Classes/CachesManagement/StarRail/Check.cs
index d44e03051..0eca1c6b5 100644
--- a/CollapseLauncher/Classes/CachesManagement/StarRail/Check.cs
+++ b/CollapseLauncher/Classes/CachesManagement/StarRail/Check.cs
@@ -29,7 +29,7 @@ private async Task> Check(List assetIndex, CancellationTo
RestartStopwatch();
// Get persistent and streaming paths
- string execName = Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName);
+ string execName = Path.GetFileNameWithoutExtension(_innerGameVersionManager.GamePreset.GameExecutableName);
string baseDesignDataPathPersistent = Path.Combine(_gamePath, @$"{execName}_Data\Persistent\DesignData\Windows");
string baseDesignDataPathStreaming = Path.Combine(_gamePath, @$"{execName}_Data\StreamingAssets\DesignData\Windows");
diff --git a/CollapseLauncher/Classes/CachesManagement/StarRail/Fetch.cs b/CollapseLauncher/Classes/CachesManagement/StarRail/Fetch.cs
index 46c219cda..4b302433b 100644
--- a/CollapseLauncher/Classes/CachesManagement/StarRail/Fetch.cs
+++ b/CollapseLauncher/Classes/CachesManagement/StarRail/Fetch.cs
@@ -9,6 +9,7 @@
using static Hi3Helper.Data.ConverterTool;
using static Hi3Helper.Locale;
using static Hi3Helper.Logger;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
namespace CollapseLauncher
{
@@ -22,7 +23,7 @@ private async Task> Fetch(CancellationToken token)
try
{
// Subscribe the event listener
- _gameVersionManager.StarRailMetadataTool.HttpEvent += _httpClient_FetchAssetProgress;
+ _innerGameVersionManager.StarRailMetadataTool.HttpEvent += _httpClient_FetchAssetProgress;
// Initialize metadata
// Set total activity string as "Fetching Caches Type: Dispatcher"
@@ -30,7 +31,7 @@ private async Task> Fetch(CancellationToken token)
_status.IsProgressTotalIndetermined = true;
_status.IsIncludePerFileIndicator = false;
UpdateStatus();
- await _gameVersionManager.StarRailMetadataTool.Initialize(token, GetExistingGameRegionID(), Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName)}_Data\\Persistent"));
+ await _innerGameVersionManager.StarRailMetadataTool.Initialize(token, GetExistingGameRegionID(), Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gameVersionManager.GamePreset.GameExecutableName)}_Data\\Persistent"));
// Iterate type and do fetch
foreach (SRAssetType type in Enum.GetValues(typeof(SRAssetType)))
@@ -62,7 +63,7 @@ private async Task> Fetch(CancellationToken token)
finally
{
// Unsubscribe the event listener and dispose Http client
- _gameVersionManager.StarRailMetadataTool.HttpEvent -= _httpClient_FetchAssetProgress;
+ _innerGameVersionManager.StarRailMetadataTool.HttpEvent -= _httpClient_FetchAssetProgress;
}
// Return asset index
@@ -84,18 +85,18 @@ private async Task> Fetch(CancellationToken token)
switch (type)
{
case SRAssetType.IFix:
- await _gameVersionManager.StarRailMetadataTool.ReadIFixMetadataInformation(token);
- assetProperty = _gameVersionManager.StarRailMetadataTool.MetadataIFix.GetAssets();
+ await _innerGameVersionManager.StarRailMetadataTool.ReadIFixMetadataInformation(token);
+ assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataIFix.GetAssets();
assetIndex.AddRange(assetProperty.AssetList);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.DesignData:
- await _gameVersionManager.StarRailMetadataTool.ReadDesignMetadataInformation(token);
- assetProperty = _gameVersionManager.StarRailMetadataTool.MetadataDesign.GetAssets();
+ await _innerGameVersionManager.StarRailMetadataTool.ReadDesignMetadataInformation(token);
+ assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataDesign.GetAssets();
assetIndex.AddRange(assetProperty.AssetList);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
case SRAssetType.Lua:
- await _gameVersionManager.StarRailMetadataTool.ReadLuaMetadataInformation(token);
- assetProperty = _gameVersionManager.StarRailMetadataTool.MetadataLua.GetAssets();
+ await _innerGameVersionManager.StarRailMetadataTool.ReadLuaMetadataInformation(token);
+ assetProperty = _innerGameVersionManager.StarRailMetadataTool.MetadataLua.GetAssets();
assetIndex.AddRange(assetProperty.AssetList);
return (assetProperty.AssetList.Count, assetProperty.AssetTotalSize);
}
@@ -112,10 +113,10 @@ private async Task> Fetch(CancellationToken token)
private unsafe string GetExistingGameRegionID()
{
#nullable enable
- object? value = GameSettings.Statics.RegistryRoot?.GetValue("App_LastServerName_h2577443795", null);
+ object? value = RegistryRoot?.GetValue("App_LastServerName_h2577443795", null);
if (value == null)
{
- return _gamePreset.GameDispatchDefaultName ?? throw new KeyNotFoundException("Default dispatcher name in metadata is not exist!");
+ return _gameVersionManager.GamePreset.GameDispatchDefaultName ?? throw new KeyNotFoundException("Default dispatcher name in metadata is not exist!");
}
#nullable disable
diff --git a/CollapseLauncher/Classes/CachesManagement/StarRail/StarRailCache.cs b/CollapseLauncher/Classes/CachesManagement/StarRail/StarRailCache.cs
index 996580544..b7ead92fe 100644
--- a/CollapseLauncher/Classes/CachesManagement/StarRail/StarRailCache.cs
+++ b/CollapseLauncher/Classes/CachesManagement/StarRail/StarRailCache.cs
@@ -1,6 +1,5 @@
using CollapseLauncher.GameVersioning;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
using Hi3Helper.Data;
using Hi3Helper.EncTool.Parser.AssetMetadata.SRMetadataAsset;
using Microsoft.UI.Xaml;
@@ -14,18 +13,20 @@ namespace CollapseLauncher
internal partial class StarRailCache : ProgressBase, ICache
{
#region Properties
+ private GameTypeStarRailVersion _innerGameVersionManager { get; set; }
private string _cacheRegionalCheckName = "sprite";
private List _updateAssetIndex { get; set; }
- private GameTypeStarRailVersion _gameVersionManager { get => PageStatics._GameVersion as GameTypeStarRailVersion; }
#endregion
- public StarRailCache(UIElement parentUI)
+ public StarRailCache(UIElement parentUI, IGameVersionCheck GameVersionManager)
: base(
parentUI,
- PageStatics._GameVersion.GameDirPath,
+ GameVersionManager,
+ GameVersionManager.GameDirPath,
null,
- PageStatics._GameVersion.GetGameVersionAPI().VersionString)
+ GameVersionManager.GetGameVersionAPI().VersionString)
{
+ _innerGameVersionManager = GameVersionManager as GameTypeStarRailVersion;
}
~StarRailCache() => Dispose();
diff --git a/CollapseLauncher/Classes/ClassesContext.cs b/CollapseLauncher/Classes/ClassesContext.cs
index 51fe31a5a..640b79fd8 100644
--- a/CollapseLauncher/Classes/ClassesContext.cs
+++ b/CollapseLauncher/Classes/ClassesContext.cs
@@ -5,18 +5,9 @@
namespace CollapseLauncher
{
[JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(CommunityToolsProperty))]
[JsonSerializable(typeof(AppUpdateVersionProp))]
- internal sealed partial class AppUpdateVersionPropContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(NotificationPush))]
- internal sealed partial class NotificationPushContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(CacheAsset))]
- internal sealed partial class CacheAssetContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(CommunityToolsProperty))]
- internal sealed partial class CommunityToolsPropertyContext : JsonSerializerContext { }
+ internal sealed partial class InternalAppJSONContext : JsonSerializerContext { }
}
diff --git a/CollapseLauncher/Classes/EventsManagement/BackgroundActivityManager.cs b/CollapseLauncher/Classes/EventsManagement/BackgroundActivityManager.cs
new file mode 100644
index 000000000..19a289bb7
--- /dev/null
+++ b/CollapseLauncher/Classes/EventsManagement/BackgroundActivityManager.cs
@@ -0,0 +1,290 @@
+using CollapseLauncher.Interfaces;
+using Hi3Helper;
+using Hi3Helper.Data;
+using Hi3Helper.Shared.Region;
+using Microsoft.UI.Text;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media;
+using Microsoft.UI.Xaml.Media.Imaging;
+using System;
+using System.Collections.Generic;
+using CollapseLauncher.Statics;
+using Hi3Helper.Preset;
+using static Hi3Helper.Locale;
+
+namespace CollapseLauncher
+{
+ internal class BackgroundActivityManager
+ {
+ private static ThemeShadow _infoBarShadow = new ThemeShadow();
+
+ public static Dictionary BackgroundActivities = new Dictionary();
+
+ private static GamePresetProperty CurrentGameProperty;
+
+ public static void Attach(int hashID, IBackgroundActivity activity, string activityTitle, string activitySubtitle)
+ {
+ if (!BackgroundActivities.ContainsKey(hashID))
+ {
+ AttachEventToNotification(hashID, activity, activityTitle, activitySubtitle);
+ BackgroundActivities.Add(hashID, activity);
+#if DEBUG
+ Logger.LogWriteLine($"Background activity with ID: {hashID} has been attached", LogType.Debug, true);
+#endif
+ return;
+ }
+ }
+
+ public static void Detach(int hashID)
+ {
+ if (BackgroundActivities.ContainsKey(hashID))
+ {
+ BackgroundActivities.Remove(hashID);
+ DetachEventFromNotification(hashID);
+#if DEBUG
+ Logger.LogWriteLine($"Background activity with ID: {hashID} has been detached", LogType.Debug, true);
+#endif
+ return;
+ }
+
+#if DEBUG
+ Logger.LogWriteLine($"Cannot detach background activity with ID: {hashID} because it doesn't attached", LogType.Debug, true);
+#endif
+ }
+
+ private static void AttachEventToNotification(int hashID, IBackgroundActivity activity, string activityTitle, string activitySubtitle)
+ {
+ Thickness containerNotClosableMargin = new Thickness(-28, -8, 24, 20);
+ Thickness containerClosableMargin = new Thickness(-28, -8, -28, 20);
+
+ InfoBar _parentNotifUI = new InfoBar()
+ {
+ Tag = hashID,
+ Severity = InfoBarSeverity.Informational,
+ Background = (Brush)Application.Current.Resources["InfoBarAnnouncementBrush"],
+ IsOpen = true,
+ IsClosable = false,
+ Margin = new Thickness(4, 4, 4, 0),
+ CornerRadius = new CornerRadius(8),
+ Shadow = _infoBarShadow,
+ Title = activityTitle,
+ Message = activitySubtitle
+ };
+ _parentNotifUI.Translation += LauncherConfig.Shadow32;
+
+ StackPanel _parentContainer = new StackPanel() { Margin = _parentNotifUI.IsClosable ? containerClosableMargin : containerNotClosableMargin };
+ _parentNotifUI.Content = _parentContainer;
+ Grid _parentGrid = new Grid()
+ {
+ ColumnDefinitions = {
+ new ColumnDefinition() { Width = new GridLength(72) },
+ new ColumnDefinition()
+ }
+ };
+ _parentContainer.Children.Add(_parentGrid);
+
+ StackPanel progressLogoContainer = new StackPanel()
+ {
+ CornerRadius = new CornerRadius(8),
+ Width = 64,
+ Height = 64,
+ Margin = new Thickness(0, 4, 8, 4)
+ };
+ _parentGrid.Children.Add(progressLogoContainer);
+ Grid.SetColumn(progressLogoContainer, 0);
+
+ CurrentGameProperty = GamePropertyVault.GetCurrentGameProperty();
+ switch (CurrentGameProperty._GameVersion.GameType)
+ {
+ case GameType.Honkai:
+ Image progressLogoHonkai = new Image()
+ {
+ Source = new BitmapImage(new Uri("ms-appx:///XAMLs/Prototype/honkai-logo.png")),
+ Width = 64,
+ Height = 64
+ };
+ progressLogoContainer.Children.Add(progressLogoHonkai);
+ break;
+ case GameType.Genshin:
+ Image progressLogoGenshin = new Image()
+ {
+ Source = new BitmapImage(new Uri("ms-appx:///XAMLs/Prototype/genshin-logo.png")),
+ Width = 64,
+ Height = 64
+ };
+ progressLogoContainer.Children.Add(progressLogoGenshin);
+ break;
+ case GameType.StarRail:
+ Image progressLogoStarRail = new Image()
+ {
+ Source = new BitmapImage(new Uri("ms-appx:///XAMLs/Prototype/starrail-logo.png")),
+ Width = 64,
+ Height = 64
+ };
+ progressLogoContainer.Children.Add(progressLogoStarRail);
+ break;
+ case GameType.Zenless:
+ Image progressLogoZenless = new Image()
+ {
+ Source = new BitmapImage(new Uri("ms-appx:///XAMLs/Prototype/zenless-logo.png")),
+ Width = 64,
+ Height = 64
+ };
+ progressLogoContainer.Children.Add(progressLogoZenless);
+ break;
+ case GameType.Unknown:
+ Image progressLogoUnknown = new Image()
+ {
+ Source = new BitmapImage(new Uri("ms-appx:///XAMLs/Prototype/honkai-logo.png")),
+ Width = 64,
+ Height = 64
+ };
+ progressLogoContainer.Children.Add(progressLogoUnknown);
+ break;
+ }
+
+ StackPanel progressStatusContainer = new StackPanel()
+ {
+ Margin = new Thickness(8, -4, 0, 0),
+ VerticalAlignment = VerticalAlignment.Center
+ };
+ _parentGrid.Children.Add(progressStatusContainer);
+ Grid.SetColumn(progressStatusContainer, 1);
+
+ Grid progressStatusGrid = new Grid()
+ {
+ Margin = new Thickness(0, 0, 0, 16),
+ ColumnDefinitions =
+ {
+ new ColumnDefinition(),
+ new ColumnDefinition()
+ },
+ RowDefinitions =
+ {
+ new RowDefinition(),
+ new RowDefinition()
+ }
+ };
+ progressStatusContainer.Children.Add(progressStatusGrid);
+
+ TextBlock progressLeftTitle = new TextBlock()
+ {
+ Style = Application.Current.Resources["BodyStrongTextBlockStyle"] as Style,
+ Text = "Downloading Package: 1 / 3"
+ };
+ TextBlock progressLeftSubtitle = new TextBlock()
+ {
+ Style = Application.Current.Resources["CaptionTextBlockStyle"] as Style,
+ Text = "Speed: 69.42 MB/s"
+ };
+
+ TextBlock progressRightTitle = new TextBlock()
+ {
+ Style = Application.Current.Resources["BodyStrongTextBlockStyle"] as Style,
+ Text = "Estimated Time: 0h 32m left",
+ HorizontalAlignment = HorizontalAlignment.Right
+ };
+ TextBlock progressRightSubtitle = new TextBlock()
+ {
+ Style = Application.Current.Resources["CaptionTextBlockStyle"] as Style,
+ Text = "Progress: 69.42%",
+ HorizontalAlignment = HorizontalAlignment.Right
+ };
+ progressStatusGrid.Children.Add(progressLeftTitle);
+ progressStatusGrid.Children.Add(progressLeftSubtitle);
+ progressStatusGrid.Children.Add(progressRightTitle);
+ progressStatusGrid.Children.Add(progressRightSubtitle);
+ Grid.SetColumn(progressLeftTitle, 0); Grid.SetRow(progressLeftTitle, 0);
+ Grid.SetColumn(progressLeftSubtitle, 0); Grid.SetRow(progressLeftSubtitle, 1);
+ Grid.SetColumn(progressRightTitle, 1); Grid.SetRow(progressRightTitle, 0);
+ Grid.SetColumn(progressRightSubtitle, 1); Grid.SetRow(progressRightSubtitle, 1);
+
+ ProgressBar progressBar = new ProgressBar() { Minimum = 0, Maximum = 100, Value = 69.42 };
+ progressStatusContainer.Children.Add(progressBar);
+
+ Button cancelButton = new Button()
+ {
+ HorizontalAlignment = HorizontalAlignment.Right,
+ Margin = new Thickness(0, 4, 0, 0),
+ CornerRadius = new CornerRadius(14),
+ Style = Application.Current.Resources["AccentButtonStyle"] as Style,
+ Content = new StackPanel()
+ {
+ Orientation = Orientation.Horizontal,
+ Margin = new Thickness(4, 0, 4, 0),
+ Children =
+ {
+ new FontIcon()
+ {
+ FontFamily = Application.Current.Resources["FontAwesomeSolid"] as FontFamily,
+ Glyph = "",
+ FontSize = 18
+ },
+ new TextBlock()
+ {
+ Text = Lang._HomePage.PauseCancelDownloadBtn,
+ FontWeight = FontWeights.Medium,
+ Margin = new Thickness(8, -2, 0, 0),
+ VerticalAlignment = VerticalAlignment.Center
+ }
+ }
+ }
+ };
+
+ cancelButton.Click += (_, args) =>
+ {
+ cancelButton.IsEnabled = false;
+ activity.CancelRoutine();
+ _parentNotifUI.IsOpen = false;
+ };
+
+ activity.ProgressChanged += (_, args) => activity.Dispatch(() =>
+ {
+ progressBar.Value = args.ProgressTotalPercentage;
+ progressLeftSubtitle.Text = string.Format(Lang._Misc.Speed, ConverterTool.SummarizeSizeSimple(args.ProgressTotalSpeed));
+ progressRightTitle.Text = string.Format(Lang._Misc.TimeRemainHMSFormat, args.ProgressTotalTimeLeft);
+ progressRightSubtitle.Text = string.Format(Lang._UpdatePage.UpdateHeader1 + " {0}%", args.ProgressTotalPercentage);
+ });
+
+ activity.StatusChanged += (_, args) => activity.Dispatch(() =>
+ {
+ progressLeftTitle.Text = args.ActivityStatus;
+ if (args.IsCanceled)
+ {
+ cancelButton.IsEnabled = false;
+ cancelButton.Visibility = Visibility.Collapsed;
+ _parentNotifUI.Severity = InfoBarSeverity.Error;
+ _parentNotifUI.Title = "[Error] " + activityTitle;
+ _parentNotifUI.IsClosable = true;
+ _parentContainer.Margin = containerClosableMargin;
+ }
+ if (args.IsCompleted)
+ {
+ cancelButton.IsEnabled = false;
+ cancelButton.Visibility = Visibility.Collapsed;
+ _parentNotifUI.Severity = InfoBarSeverity.Success;
+ _parentNotifUI.Title = "[Completed] " + activityTitle;
+ _parentNotifUI.IsClosable = true;
+ _parentContainer.Margin = containerClosableMargin;
+ }
+ if (args.IsRunning)
+ {
+ cancelButton.IsEnabled = true;
+ cancelButton.Visibility = Visibility.Visible;
+ _parentNotifUI.Severity = InfoBarSeverity.Informational;
+ _parentNotifUI.Title = activityTitle;
+ _parentNotifUI.IsClosable = false;
+ _parentContainer.Margin = containerNotClosableMargin;
+ }
+ });
+
+ _parentNotifUI.Closing += (_, _) => Detach(hashID);
+ _parentContainer.Children.Add(cancelButton);
+
+ NotificationSender.SendCustomNotification(hashID, _parentNotifUI);
+ }
+
+ private static void DetachEventFromNotification(int hashID) => NotificationSender.RemoveCustomNotification(hashID);
+ }
+}
diff --git a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
index c60854b6c..4fd910be5 100644
--- a/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
+++ b/CollapseLauncher/Classes/EventsManagement/EventsHandler.cs
@@ -73,7 +73,7 @@ private static async ValueTask GetUpdateMetadata()
await FallbackCDNUtil.DownloadCDNFallbackContent(client, ms, relativePath, default);
ms.Position = 0;
- return (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), AppUpdateVersionPropContext.Default);
+ return (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), InternalAppJSONContext.Default);
}
}
@@ -235,6 +235,25 @@ internal static class NotificationSender
{
static NotificationInvoker invoker = new NotificationInvoker();
public static void SendNotification(NotificationInvokerProp e) => invoker.SendNotification(e);
+ public static void SendCustomNotification(int tagID, InfoBar infoBarUI) => invoker.SendNotification(new NotificationInvokerProp
+ {
+ IsCustomNotif = true,
+ CustomNotifAction = NotificationCustomAction.Add,
+ Notification = new NotificationProp
+ {
+ MsgId = tagID,
+ },
+ OtherContent = infoBarUI
+ });
+ public static void RemoveCustomNotification(int tagID) => invoker.SendNotification(new NotificationInvokerProp
+ {
+ IsCustomNotif = true,
+ CustomNotifAction = NotificationCustomAction.Remove,
+ Notification = new NotificationProp
+ {
+ MsgId = tagID,
+ }
+ });
}
internal class NotificationInvoker
@@ -243,12 +262,16 @@ internal class NotificationInvoker
public void SendNotification(NotificationInvokerProp e) => EventInvoker?.Invoke(this, e);
}
+ public enum NotificationCustomAction { Add, Remove }
public class NotificationInvokerProp
{
public TypedEventHandler CloseAction { get; set; } = null;
public UIElement OtherContent { get; set; } = null;
public NotificationProp Notification { get; set; }
public bool IsAppNotif { get; set; } = true;
+ public bool IsCustomNotif { get; set; } = false;
+ public NotificationCustomAction CustomNotifAction { get; set; }
+
}
#endregion
#region BackgroundRegion
@@ -257,14 +280,17 @@ internal static class BackgroundImgChanger
static BackgroundImgChangerInvoker invoker = new BackgroundImgChangerInvoker();
public static async Task WaitForBackgroundToLoad() => await invoker.WaitForBackgroundToLoad();
public static void ChangeBackground(string ImgPath, bool IsCustom = true) => invoker.ChangeBackground(ImgPath, IsCustom);
+ public static void ToggleBackground(bool Hide) => invoker.ToggleBackground(Hide);
}
internal class BackgroundImgChangerInvoker
{
public static event EventHandler ImgEvent;
+ public static event EventHandler IsImageHide;
BackgroundImgProperty property;
public async Task WaitForBackgroundToLoad() => await Task.Run(() => { while (!property.IsImageLoaded) { } });
public void ChangeBackground(string ImgPath, bool IsCustom) => ImgEvent?.Invoke(this, property = new BackgroundImgProperty(ImgPath, IsCustom));
+ public void ToggleBackground(bool Hide) => IsImageHide?.Invoke(this, Hide);
}
internal class BackgroundImgProperty
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/ImportExportBase.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/ImportExportBase.cs
index 4fd03252e..66a195516 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/ImportExportBase.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/ImportExportBase.cs
@@ -7,8 +7,8 @@
using System.IO;
using System.IO.Compression;
using System.Text;
-using static CollapseLauncher.GameSettings.Statics;
using static Hi3Helper.Locale;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
namespace CollapseLauncher.GameSettings.Base
{
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/SettingsBase.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/SettingsBase.cs
new file mode 100644
index 000000000..faa5da052
--- /dev/null
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/SettingsBase.cs
@@ -0,0 +1,19 @@
+using CollapseLauncher.Interfaces;
+using Microsoft.Win32;
+
+namespace CollapseLauncher.GameSettings.Base
+{
+ internal class SettingsBase : ImportExportBase
+ {
+#nullable enable
+ internal static string? RegistryPath;
+ internal static RegistryKey? RegistryRoot;
+
+ public SettingsBase(IGameVersionCheck GameVersionManager)
+ {
+ _gameVersionManager = GameVersionManager;
+ }
+#nullable disable
+ protected static IGameVersionCheck _gameVersionManager { get; set; }
+ }
+}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/TypeExtensions.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/TypeExtensions.cs
new file mode 100644
index 000000000..aa4934044
--- /dev/null
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/BaseClass/TypeExtensions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Reflection;
+
+namespace CollapseLauncher
+{
+ public static class TypeExtensions
+ {
+ public static bool IsInstancePropertyEqual(T self, T to) where T : class
+ {
+ // Check if the one of the value is null, if true check the other value if it's null
+ if (self == null)
+ {
+ if (to != null) return false;
+ else return true;
+ }
+ if (to == null)
+ {
+ if (self != null) return false;
+ else return true;
+ }
+
+ // Get the type of the instance
+ Type type = typeof(T);
+ // Enumerate the PropertyInfo out of instance
+ foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
+ {
+ // Get the property name and value from both self and to
+ object selfValue = type.GetProperty(pi.Name).GetValue(self, null);
+ object toValue = type.GetProperty(pi.Name).GetValue(to, null);
+
+ // If the value on both self and to is different, then return false (not equal)
+ if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
+ {
+ return false;
+ }
+ }
+
+ // If all passes, then return true (equal)
+ return true;
+ }
+ }
+}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Context.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Context.cs
index 8bf35b30e..76d74071b 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Context.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Context.cs
@@ -1,17 +1,10 @@
-using CollapseLauncher.GameSettings.Genshin;
-using System.Text.Json.Serialization;
+using System.Text.Json.Serialization;
namespace CollapseLauncher.GameSettings.Genshin.Context
{
[JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(GeneralData))]
- internal sealed partial class GeneralDataContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(GraphicsData))]
- internal sealed partial class GraphicsDataContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(GlobalPerfData))]
- internal sealed partial class GlobalPerfDataContext : JsonSerializerContext { }
+ internal sealed partial class GenshinSettingsJSONContext : JsonSerializerContext { }
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GeneralData.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GeneralData.cs
index 0b535cf92..eba4045f7 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GeneralData.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GeneralData.cs
@@ -1,14 +1,13 @@
-using CollapseLauncher.GameSettings.Genshin;
using CollapseLauncher.GameSettings.Genshin.Context;
-using CollapseLauncher.Interfaces;
using Hi3Helper;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Text;
+using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Genshin
@@ -24,77 +23,40 @@ internal class GeneralData
//Using guide from https://github.com/Myp3a/GenshinConfigurator/wiki/Config-format
//Thanks Myp3a!
- ///
- /// deviceUUID
- /// This is supposed to be empty
- ///
- public string deviceUUID { get; set; } = "";
-
- ///
- /// userLocalDataVersionId
- /// This should be static
- /// Value: 0.0.1
- ///
- public string userLocalDataVersionId { get; set; } = "0.0.1";
+ public int mtrAbortTimeOutCount { get; set; } = 3;
///
- /// This define "Text Language " in-game settings.
- /// Valid values: 1-13
- /// Default: 1
- /// English(1)
- /// Simplified Chinese(2)
- /// Traditional Chinese(3)
- /// French(4)
- /// German(5)
- /// Spanish(6)
- /// Portugese(7)
- /// Russian(8)
- /// Japanese(9)
- /// Korean(10)
- /// Thai(11)
- /// Vietnamese(12)
- /// Indonesian(13)
- /// Turkish(14)
- /// Italy(15)
+ /// Could be for PlayStation multiplayer stuff
///
- public int deviceLanguageType { get; set; } = 1;
+ public bool onlyPlayWithPSPlayer { get; set; } = false;
- ///
- /// This define "Voice Language " in-game settings.
- /// Valid values: 0-3
- /// Default: 1
- /// Chinese(0)
- /// English(1)
- /// Japanese(2)
- /// Korean(3)
- ///
- public int deviceVoiceLanguageType { get; set; } = 1;
+ public int urlCheckErrorTraceCount { get; set; } = 30;
- ///
- /// This define "Server Name " last selected in loading menu.
- ///
- public string selectedServerName { get; set; } = "os_usa";
+ public decimal uiPaperWhite { get; set; } = 0.0m;
+ public decimal scenePaperWhite { get; set; } = 0.0m;
- ///
- /// I don't know what this do
- ///
public int localLevelIndex { get; set; } = 0;
- public string deviceID { get; set; } = "";
- public string targetUID { get; set; } = "";
- public string curAccountName { get; set; } = "";
+ public bool disableRewiredDelayInit { get; set; } = false;
+ public bool enableAudioChangeAndroidMinimumBufferCapacity { get; set; } = true;
///
- /// This define "Resolution " index selected in-game.
- /// Valid value: 0-?
- /// Default: 0
+ /// This define "Voice Volume " slider in-game.
+ /// Valid values: 0-10
+ /// Default: 10
///
- public string uiSaveData { get; set; }
+ public int volumeVoice { get; set; } = 10;
+
+ public int mtrTraceCDEachReason { get; set; } = 600;
+ public bool mtrCached { get; set; } = true;
+ public List urlCheckBanReasons { get; set; }
///
- /// This holds settings for input sens and stuff.
- /// Please look at https://github.com/Myp3a/GenshinConfigurator/wiki/Config-format#input-data-format
+ /// This define "Server Name " last selected in loading menu.
///
- public string inputData { get; set; }
+ public string selectedServerName { get; set; } = "os_usa";
+
+ public int urlCheckTimeInterval { get; set; } = 1000;
+ public int lastSeenPreDownloadTime { get; set; } = 0;
///
/// This holds settings that holds Graphics Settings settings. YEP!
@@ -107,30 +69,35 @@ internal class GeneralData
[JsonIgnore]
public GraphicsData graphicsData { get; set; }
+ public bool completionPlayGoPkg { get; set; } = false;
+
///
- /// This is a dict that keeps track of graphics settings changes.
- /// Save to ignore (?)
+ /// This defines "Gamma " slider in-game.
+ /// This implementation is quite janky but hear me out
+ /// The value is directly controlled by Gamma Slider, which linked with GammaValue (NumberBox)
+ /// Since the value is flipped, math function of y = -x + 4.4 is used (Refer GenshinGameSettingsPage.Ext.cs Line 122)
///
- // Temporary for fallback before the implementation is made
- [JsonIgnore]
- public GlobalPerfData globalPerfData { get; set; }
-
- [JsonPropertyName("globalPerfData")]
- public string _globalPerfData { get; set; }
+ public double gammaValue { get; set; } = 2.2f;
- //[JsonIgnore]
- //public globalPerfData globalPerfData { get; set; }
+ public bool mtrIsOpen { get; set; } = true;
///
- /// Something about minimap config ?
+ /// This defines "Vibration Intensity " slider in-game.
+ /// Valid Values: 1-5
+ /// Default: 5
///
- public int miniMapConfig { get; set; } = 1;
+ public int vibrationIntensity { get; set; } = 5;
+
+ public bool needPlayGoFullPkgPatch { get; set; } = false;
+ public bool exploreNotification { get; set; } = true;
+ public int mtrMaxTTL { get; set; } = 32;
+ public bool urlCheckCached { get; set; } = false;
///
- /// This defines "Automatic View Height " in-game settings.
- /// Default: true
+ /// deviceUUID
+ /// This is supposed to be empty
///
- public bool enableCameraSlope { get; set; } = true;
+ public string deviceUUID { get; set; } = "";
///
/// This defines "Smart combat camera " whatever that is.
@@ -138,59 +105,65 @@ internal class GeneralData
///
public bool enableCameraCombatLock { get; set; } = true;
- ///
- /// not sure either what these does.
- ///
- public bool completionPkg { get; set; } = false;
- public bool completionPlayGoPkg { get; set; } = false;
+ public bool enableEffectAssembleInEditor { get; set; } = true;
+ public bool resinNotification { get; set; } = true;
///
- /// Could be for PlayStation multiplayer stuff
+ /// This define "Voice Language " in-game settings.
+ /// Valid values: 0-3
+ /// Default: 1
+ /// Chinese(0)
+ /// English(1)
+ /// Japanese(2)
+ /// Korean(3)
///
- public bool onlyPlayWithPSPlayer { get; set; } = false;
+ public int deviceVoiceLanguageType { get; set; } = 1;
- ///
- /// Mysterious~
- ///
- public bool needPlayGoFullPkgPatch { get; set; } = false;
+ public string curAccountName { get; set; } = "";
+ public bool _audioSuccessInit { get; set; } = true;
+ public bool urlCheckAllIP { get; set; } = false;
+ public bool rewiredDisableKeyboard { get; set; } = false;
///
- /// Mobile notification stuff
+ /// This defines "Audio Output " combo box in-game.
+ /// Valid Values: 0 (stereo), 1 (surround)
+ /// Default: 0
///
- public bool resinNotification { get; set; } = true;
- public bool exploreNotification { get; set; } = true;
+ public int audioOutput { get; set; } = 0;
- ///
- /// This define "Global Volume " slider in-game.
- /// Valid values: 0-10
- /// Default: 10
- ///
- public int volumeGlobal { get; set; } = 10;
+ public int miniMapConfig { get; set; } = 1;
///
- /// This define "SFX Volume " slider in-game.
- /// Valid values: 0-10
- /// Default: 10
+ /// This defines "Automatic View Height " in-game settings.
+ /// Default: true
///
- public int volumeSFX { get; set; } = 10;
+ public bool enableCameraSlope { get; set; } = true;
///
- /// This define "Music Volume " slider in-game.
- /// Valid values: 0-10
- /// Default: 10
+ /// This define vibration level for certain controller probably ?
+ /// Valid Values: 0 (Full), 1 (Partial), 2 (Off)
+ /// Default: 0
///
- public int volumeMusic { get; set; } = 10;
+ public int vibrationLevel { get; set; } = 0;
- ///
- /// This define "Voice Volume " slider in-game.
- /// Valid values: 0-10
- /// Default: 10
- ///
- public int volumeVoice { get; set; } = 10;
+ public string deviceID { get; set; } = "";
+ public string uiSaveData { get; set; }
+ public bool gyroAiming { get; set; } = false;
+ public bool motionBlur { get; set; } = true;
+ public bool completionPkg { get; set; } = false;
+ public int audioAndroidMiniumBufferCapacity { get; set; } = 2048;
///
- /// Probably just leave it alone...
+ /// This is a dict that keeps track of graphics settings changes.
+ /// Save to ignore (?)
///
+ [JsonIgnore]
+ public GlobalPerfData globalPerfData { get; set; }
+
+ [JsonPropertyName("globalPerfData")]
+ public string _globalPerfData { get; set; }
+
+ public int urlCheckTimeOut { get; set; } = 5000;
public int audioAPI { get; set; } = -1;
///
@@ -200,117 +173,104 @@ internal class GeneralData
///
public int audioDynamicRange { get; set; } = 0;
- ///
- /// This defines "Audio Output " combo box in-game.
- /// Valid Values: 0 (stereo), 1 (surround)
- /// Default: 0
- ///
- public int audioOutput { get; set; } = 0;
+ public bool firstHDRSetting { get; set; } = true;
+ public int mtrTraceCount { get; set; } = 5;
+ public bool disableRewiredInitProtection { get; set; } = false;
+ public string greyTestDeviceUniqueId { get; set; } = "";
+ public bool mtrUseOldWinVersion { get; set; } = false;
+ public List _serializedCodeSwitches { get; set; }
+ public int urlCheckAbortTimeOutCount { get; set; } = 3;
+ public int urlCheckSueecssTraceCount { get; set; } = 5; //yes, that is actually the class name, its not a typo by us...
///
- /// Audio related stuff...
+ /// This define "Music Volume " slider in-game.
+ /// Valid values: 0-10
+ /// Default: 10
///
- public bool _audioSuccessInit { get; set; } = true;
- public bool enableAudioChangeAndroidMinimumBufferCapacity { get; set; } = true;
- public int audioAndroidMiniumBufferCapacity { get; set; } = 2048;
+ public int volumeMusic { get; set; } = 10;
///
- /// This define vibration level for certain controller probably ?
- /// Valid Values: 0 (Full), 1 (Partial), 2 (Off)
- /// Default: 0
+ /// This holds value for controllers input that has been customized.
///
- public int vibrationLevel { get; set; } = 0;
+ public List _overrideControllerMapKeyList { get; set; }
+
+ public bool urlCheckIsOpen { get; set; } = false;
+ public int urlCheckCDEachReason { get; set; } = 600;
+ public List _customDataValueList { get; set; }
///
- /// This defines "Vibration Intensity " slider in-game.
- /// Valid Values: 1-5
- /// Default: 5
+ /// This define "Text Language " in-game settings.
+ /// Valid values: 1-13
+ /// Default: 1
+ /// English(1)
+ /// Simplified Chinese(2)
+ /// Traditional Chinese(3)
+ /// French(4)
+ /// German(5)
+ /// Spanish(6)
+ /// Portugese(7)
+ /// Russian(8)
+ /// Japanese(9)
+ /// Korean(10)
+ /// Thai(11)
+ /// Vietnamese(12)
+ /// Indonesian(13)
+ /// Turkish(14)
+ /// Italy(15)
///
- public int vibrationIntensity { get; set; } = 5;
+ public int deviceLanguageType { get; set; } = 1;
+
+ public List _customDataKeyList { get; set; }
+ public List mtrBanReasons { get; set; }
+ public int mtrTimeInterval { get; set; } = 1000;
///
- /// Some vibration related stuff ?
+ /// This define "SFX Volume " slider in-game.
+ /// Valid values: 0-10
+ /// Default: 10
///
- public bool usingNewVibrationSetting { get; set; } = true;
+ public int volumeSFX { get; set; } = 10;
+
+ public int mtrAutoTraceInterval { get; set; } = 3600;
+ public bool needReportQuestResourceDeleteStatusFiles { get; set; } = false;
///
- /// Is not an actual blur setting
+ /// This holds said override for those controllers.
///
- public bool motionBlur { get; set; } = true;
+ // Temporary for fallback before the implementation is made
+ public List _overrideControllerMapValueList { get; set; }
+
+ public int mtrTimeOut { get; set; } = 5000;
///
- /// Gyro Aiming stuff, most likely not used in PC.
+ /// This define "Global Volume " slider in-game.
+ /// Valid values: 0-10
+ /// Default: 10
///
- public bool gyroAiming { get; set; } = false;
+ public int volumeGlobal { get; set; } = 10;
- //unsure what these does, probably HDR stuff? doesn't have HDR monitor to test...
- public bool firstHDRSetting { get; set; } = true;
public decimal maxLuminosity { get; set; } = 0.0m;
- public decimal uiPaperWhite { get; set; } = 0.0m;
- public decimal scenePaperWhite { get; set; } = 0.0m;
///
- /// This defines "Gamma " slider in-game.
- /// This implementation is quite janky but hear me out
- /// The value is directly controlled by Gamma Slider, which linked with GammaValue (NumberBox)
- /// Since the value is flipped, math function of y = -x + 4.4 is used (Refer GenshinGameSettingsPage.Ext.cs Line 122)
- ///
- public double gammaValue { get; set; } = 2.2f;
-
- ///
- /// This holds value for controllers input that has been customized.
+ /// userLocalDataVersionId
+ /// This should be static
+ /// Empty value
///
- public List _overrideControllerMapKeyList { get; set; }
+ public string userLocalDataVersionId { get; set; } = "";
+ public bool forceDisableQuestResourceManagement { get; set; } = false;
+ public bool rewiredEnableEDS { get; set; } = false;
+ public bool usingNewVibrationSetting { get; set; } = true;
///
- /// This holds said override for those controllers.
+ /// This holds settings for input sens and stuff.
+ /// Please look at https://github.com/Myp3a/GenshinConfigurator/wiki/Config-format#input-data-format
///
- // Temporary for fallback before the implementation is made
- public List _overrideControllerMapValueList { get; set; }
-
- //[JsonPropertyName("_overrideControllerMapValueList")]
- //public List __overrideControllerMapValueList { get; set; }
-
- //[JsonIgnore]
- //public Controllers _overrideControllerMapValueList { get; set; }
+ public string inputData { get; set; }
- //misc values
- //just, idk, ignore?
- public bool rewiredDisableKeyboard { get; set; } = false;
+ public string targetUID { get; set; } = "";
public bool rewiredEnableKeyboard { get; set; } = false;
- public bool rewiredEnableEDS { get; set; } = false;
- public bool disableRewiredDelayInit { get; set; } = false;
- public bool disableRewiredInitProtection { get; set; } = false;
- public int lastSeenPreDownloadTime { get; set; } = 0;
- public bool enableEffectAssembleInEditor { get; set; } = true;
- public bool forceDisableQuestResourceManagement { get; set; } = false;
- public bool needReportQuestResourceDeleteStatusFiles { get; set; } = false;
- public bool mtrCached { get; set; } = true;
- public bool mtrIsOpen { get; set; } = true;
- public int mtrMaxTTL { get; set; } = 32;
- public int mtrTimeOut { get; set; } = 5000;
- public int mtrTraceCount { get; set; } = 5;
- public int mtrAbortTimeOutCount { get; set; } = 3;
- public int mtrAutoTraceInterval { get; set; } = 3600;
- public int mtrTraceCDEachReason { get; set; } = 600;
- public int mtrTimeInterval { get; set; } = 1000;
- public List mtrBanReasons { get; set; }
- public List _customDataKeyList { get; set; }
- public List _customDataValueList { get; set; }
- public List _serializedCodeSwitches { get; set; }
- public bool urlCheckCached { get; set; } = false;
- public bool urlCheckIsOpen { get; set; } = false;
- public bool urlCheckAllIP { get; set; } = false;
- public int urlCheckTimeOut { get; set; } = 5000;
- public int urlCheckSueecssTraceCount { get; set; } = 5;
- public int urlCheckErrorTraceCount { get; set; } = 30;
- public int urlCheckAbortTimeOutCount { get; set; } = 3;
- public int urlCheckTimeInterval { get; set; } = 1000;
- public int urlCheckCDEachReason { get; set; } = 600;
- public List urlCheckBanReasons { get; set; }
- public bool mtrUseOldWinVersion { get; set; } = false;
- public string greyTestDeviceUniqueId { get; set; } = "";
+
#endregion
#region Methods
@@ -331,7 +291,12 @@ public static GeneralData Load()
// WARNING: VERY EXPENSIVE CPU TIME WILL BE USED
LogWriteLine($"Loaded Genshin Settings: {_ValueName}", LogType.Debug, true);
#endif
- GeneralData data = (GeneralData?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(GeneralData), GeneralDataContext.Default) ?? new GeneralData();
+ JsonSerializerOptions options = new JsonSerializerOptions()
+ {
+ TypeInfoResolver = GenshinSettingsJSONContext.Default,
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+ };
+ GeneralData data = (GeneralData?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(GeneralData), options) ?? new GeneralData();
data.graphicsData = GraphicsData.Load(data._graphicsData);
data.globalPerfData = new();
return data;
@@ -353,8 +318,12 @@ public void Save()
_graphicsData = graphicsData.Save();
_globalPerfData = globalPerfData.Create(graphicsData, graphicsData.volatileVersion);
-
- string data = JsonSerializer.Serialize(this, typeof(GeneralData), GeneralDataContext.Default) + '\0';
+ JsonSerializerOptions options = new JsonSerializerOptions()
+ {
+ TypeInfoResolver = GenshinSettingsJSONContext.Default,
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+ };
+ string data = JsonSerializer.Serialize(this, typeof(GeneralData), options) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -381,89 +350,7 @@ public void Save()
}
}
- public bool Equals(GeneralData? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- // nightmare nightmare nightmare nightmare nightmare
- return comparedTo.deviceUUID == deviceUUID &&
- comparedTo.userLocalDataVersionId == userLocalDataVersionId &&
- comparedTo.deviceLanguageType == deviceLanguageType &&
- comparedTo.deviceVoiceLanguageType == deviceVoiceLanguageType &&
- comparedTo.selectedServerName == selectedServerName &&
- comparedTo.localLevelIndex == localLevelIndex &&
- comparedTo.deviceID == deviceID &&
- comparedTo.targetUID == targetUID &&
- comparedTo.uiSaveData == uiSaveData &&
- comparedTo.inputData == inputData &&
- comparedTo.graphicsData == graphicsData &&
- comparedTo.globalPerfData == globalPerfData &&
- comparedTo.miniMapConfig == miniMapConfig &&
- comparedTo.enableCameraSlope == enableCameraSlope &&
- comparedTo.enableCameraCombatLock == enableCameraCombatLock &&
- comparedTo.completionPkg == completionPkg &&
- comparedTo.completionPlayGoPkg == completionPlayGoPkg &&
- comparedTo.onlyPlayWithPSPlayer == onlyPlayWithPSPlayer &&
- comparedTo.needPlayGoFullPkgPatch == needPlayGoFullPkgPatch &&
- comparedTo.resinNotification == resinNotification &&
- comparedTo.exploreNotification == exploreNotification &&
- comparedTo.volumeGlobal == volumeGlobal &&
- comparedTo.volumeSFX == volumeSFX &&
- comparedTo.volumeVoice == volumeVoice &&
- comparedTo.audioAPI == audioAPI &&
- comparedTo.audioDynamicRange == audioDynamicRange &&
- comparedTo.audioOutput == audioOutput &&
- comparedTo._audioSuccessInit == _audioSuccessInit &&
- comparedTo.enableAudioChangeAndroidMinimumBufferCapacity == enableAudioChangeAndroidMinimumBufferCapacity &&
- comparedTo.audioAndroidMiniumBufferCapacity == audioAndroidMiniumBufferCapacity &&
- comparedTo.vibrationLevel == vibrationLevel &&
- comparedTo.vibrationIntensity == vibrationIntensity &&
- comparedTo.usingNewVibrationSetting == usingNewVibrationSetting &&
- comparedTo.motionBlur == motionBlur &&
- comparedTo.gyroAiming == gyroAiming &&
- comparedTo.firstHDRSetting == firstHDRSetting &&
- comparedTo.maxLuminosity == maxLuminosity &&
- comparedTo.uiPaperWhite == uiPaperWhite &&
- comparedTo.scenePaperWhite == scenePaperWhite &&
- comparedTo.gammaValue == gammaValue &&
- comparedTo._overrideControllerMapKeyList == _overrideControllerMapKeyList &&
- comparedTo._overrideControllerMapValueList == _overrideControllerMapValueList &&
- comparedTo.rewiredDisableKeyboard == rewiredDisableKeyboard &&
- comparedTo.rewiredEnableKeyboard == rewiredEnableKeyboard &&
- comparedTo.rewiredEnableEDS == rewiredEnableEDS &&
- comparedTo.disableRewiredDelayInit == disableRewiredDelayInit &&
- comparedTo.disableRewiredInitProtection == disableRewiredInitProtection &&
- comparedTo.lastSeenPreDownloadTime == lastSeenPreDownloadTime &&
- comparedTo.enableEffectAssembleInEditor == enableEffectAssembleInEditor &&
- comparedTo.forceDisableQuestResourceManagement == forceDisableQuestResourceManagement &&
- comparedTo.needReportQuestResourceDeleteStatusFiles == needReportQuestResourceDeleteStatusFiles &&
- comparedTo.mtrCached == mtrCached &&
- comparedTo.mtrIsOpen == mtrIsOpen &&
- comparedTo.mtrMaxTTL == mtrMaxTTL &&
- comparedTo.mtrTimeOut == mtrTimeOut &&
- comparedTo.mtrTraceCount == mtrTraceCount &&
- comparedTo.mtrAbortTimeOutCount == mtrAbortTimeOutCount &&
- comparedTo.mtrAutoTraceInterval == mtrAutoTraceInterval &&
- comparedTo.mtrTraceCDEachReason == mtrTraceCDEachReason &&
- comparedTo.mtrTimeInterval == mtrTimeInterval &&
- comparedTo.mtrBanReasons == mtrBanReasons &&
- comparedTo._customDataKeyList == _customDataKeyList &&
- comparedTo._customDataValueList == _customDataValueList &&
- comparedTo._serializedCodeSwitches == _serializedCodeSwitches &&
- comparedTo.urlCheckCached == urlCheckCached &&
- comparedTo.urlCheckIsOpen == urlCheckIsOpen &&
- comparedTo.urlCheckAllIP == urlCheckAllIP &&
- comparedTo.urlCheckTimeOut == urlCheckTimeOut &&
- comparedTo.urlCheckSueecssTraceCount == urlCheckSueecssTraceCount &&
- comparedTo.urlCheckErrorTraceCount == urlCheckErrorTraceCount &&
- comparedTo.urlCheckAbortTimeOutCount == urlCheckAbortTimeOutCount &&
- comparedTo.urlCheckTimeInterval == urlCheckTimeInterval &&
- comparedTo.urlCheckCDEachReason == urlCheckCDEachReason &&
- comparedTo.urlCheckBanReasons == urlCheckBanReasons &&
- comparedTo.mtrUseOldWinVersion == mtrUseOldWinVersion &&
- comparedTo.greyTestDeviceUniqueId == greyTestDeviceUniqueId;
- }
+ public bool Equals(GeneralData? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#nullable disable
#endregion
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GlobalPerfData.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GlobalPerfData.cs
index 1fb745993..09bcd11ae 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GlobalPerfData.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GlobalPerfData.cs
@@ -1,8 +1,4 @@
-using CollapseLauncher.GameSettings.Genshin;
using CollapseLauncher.GameSettings.Genshin.Context;
-using CollapseLauncher.GameSettings.Genshin.Enums;
-using Hi3Helper;
-using System;
using System.Collections.Generic;
using System.Text.Json;
using static Hi3Helper.Logger;
@@ -18,24 +14,41 @@ internal class PerfDataItem
#endregion
#region Methods
- public PerfDataItem(int entryType, int index, string itemVersion) {
+ public PerfDataItem(int entryType, int index, string itemVersion)
+ {
this.entryType = entryType;
this.index = index;
this.itemVersion = itemVersion;
}
#endregion
}
+
+ internal class GenshinKeyValuePair
+ {
+ #region Properties
+ public int key { get; set; }
+ public int value { get; set; }
+ #endregion
+
+ #region Methods
+ public GenshinKeyValuePair(int Key, int Value)
+ {
+ key = Key;
+ value = Value;
+ }
+ #endregion
+ }
+
internal class GlobalPerfData
{
#region Properties
public List saveItems { get; set; } = new();
public bool truePortedFromGraphicData { get; set; } = true;
- public string portedVersion { get; set; } = "OSRELWin3.7.0";
+ public string portedVersion { get; set; } = "OSRELWin3.8.0";
public bool portedFromGraphicsData { get; set; } = false;
#endregion
#region Methods
-
public string Create(GraphicsData graphics, string version)
{
saveItems = new()
@@ -57,9 +70,9 @@ public string Create(GraphicsData graphics, string version)
new PerfDataItem (15,(int) graphics.SubsurfaceScattering - 1, version),
new PerfDataItem (17,(int) graphics.AnisotropicFiltering - 1, version),
};
- string data = JsonSerializer.Serialize(this, typeof(GlobalPerfData), GlobalPerfDataContext.Default);
+ string data = JsonSerializer.Serialize(this, typeof(GlobalPerfData), GenshinSettingsJSONContext.Default);
#if DEBUG
- LogWriteLine($"Saved Genshin GlobalPerfData\r\n{data}", LogType.Debug, true);
+ LogWriteLine($"Saved Genshin GlobalPerfData\r\n{data}", Hi3Helper.LogType.Debug, true);
#endif
return data;
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GraphicsData.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GraphicsData.cs
index 6dba085e5..6f0f75bca 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GraphicsData.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/GraphicsData.cs
@@ -1,12 +1,13 @@
using CollapseLauncher.GameSettings.Genshin.Context;
using CollapseLauncher.GameSettings.Genshin.Enums;
-using Hi3Helper;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.Encodings.Web;
using System.Text.Json;
-using static Hi3Helper.Logger;
+using Hi3Helper;
+using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Genshin
{
internal class GraphicsData
@@ -29,7 +30,7 @@ private static int GetFPSOptionNumber(FPSOption value)
public static readonly decimal[] RenderScaleIndex = new decimal[] { 0.6m, 0.8m, 1.0m, 1.1m, 1.2m, 1.3m, 1.4m, 1.5m };
public int currentVolatielGrade { get; set; } = -1;
- public List> customVolatileGrades { get; set; } = new();
+ public List customVolatileGrades { get; set; } = new();
public string volatileVersion { get; set; } = "";
#endregion
@@ -149,102 +150,103 @@ private static int GetFPSOptionNumber(FPSOption value)
#endregion
#region Methods
+#nullable enable
public static GraphicsData Load(string graphicsJson)
{
- GraphicsData graphics = (GraphicsData?)JsonSerializer.Deserialize(graphicsJson, typeof(GraphicsData), GraphicsDataContext.Default) ?? new GraphicsData();
- foreach (Dictionary setting in graphics.customVolatileGrades)
+ GraphicsData graphics = (GraphicsData?)JsonSerializer.Deserialize(graphicsJson, typeof(GraphicsData), GenshinSettingsJSONContext.Default) ?? new GraphicsData();
+ foreach (GenshinKeyValuePair setting in graphics.customVolatileGrades)
{
- switch (setting["key"])
+ switch (setting.key)
{
case 1:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - FPS: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - FPS: {setting.value}", LogType.Debug, true);
#endif
- graphics.FPS = (FPSOption)setting["value"];
+ graphics.FPS = (FPSOption)setting.value;
break;
case 2:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Render Resolution: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Render Resolution: {setting.value}", LogType.Debug, true);
#endif
- graphics.RenderResolution = (RenderResolutionOption)setting["value"];
+ graphics.RenderResolution = (RenderResolutionOption)setting.value;
break;
case 3:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Shadow Quality: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Shadow Quality: {setting.value}", LogType.Debug, true);
#endif
- graphics.ShadowQuality = (ShadowQualityOption)setting["value"];
+ graphics.ShadowQuality = (ShadowQualityOption)setting.value;
break;
case 4:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Visual Effects: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Visual Effects: {setting.value}", LogType.Debug, true);
#endif
- graphics.VisualEffects = (VisualEffectsOption)setting["value"];
+ graphics.VisualEffects = (VisualEffectsOption)setting.value;
break;
case 5:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - SFX Quality: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - SFX Quality: {setting.value}", LogType.Debug, true);
#endif
- graphics.SFXQuality = (SFXQualityOption)setting["value"];
+ graphics.SFXQuality = (SFXQualityOption)setting.value;
break;
case 6:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Environment Detail: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Environment Detail: {setting.value}", LogType.Debug, true);
#endif
- graphics.EnvironmentDetail = (EnvironmentDetailOption)setting["value"];
+ graphics.EnvironmentDetail = (EnvironmentDetailOption)setting.value;
break;
case 7:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Vertical Sync: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Vertical Sync: {setting.value}", LogType.Debug, true);
#endif
- graphics.VerticalSync = (VerticalSyncOption)setting["value"];
+ graphics.VerticalSync = (VerticalSyncOption)setting.value;
break;
case 8:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Antialiasing: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Antialiasing: {setting.value}", LogType.Debug, true);
#endif
- graphics.Antialiasing = (AntialiasingOption)setting["value"];
+ graphics.Antialiasing = (AntialiasingOption)setting.value;
break;
case 9:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Volumetric Fog: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Volumetric Fog: {setting.value}", LogType.Debug, true);
#endif
- graphics.VolumetricFog = (VolumetricFogOption)setting["value"];
+ graphics.VolumetricFog = (VolumetricFogOption)setting.value;
break;
case 10:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Reflections: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Reflections: {setting.value}", LogType.Debug, true);
#endif
- graphics.Reflections = (ReflectionsOption)setting["value"];
+ graphics.Reflections = (ReflectionsOption)setting.value;
break;
case 11:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Motion Blur: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Motion Blur: {setting.value}", LogType.Debug, true);
#endif
- graphics.MotionBlur = (MotionBlurOption)setting["value"];
+ graphics.MotionBlur = (MotionBlurOption)setting.value;
break;
case 12:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Bloom: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Bloom: {setting.value}", LogType.Debug, true);
#endif
- graphics.Bloom = (BloomOption)setting["value"];
+ graphics.Bloom = (BloomOption)setting.value;
break;
case 13:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Crowd Density: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Crowd Density: {setting.value}", LogType.Debug, true);
#endif
- graphics.CrowdDensity = (CrowdDensityOption)setting["value"];
+ graphics.CrowdDensity = (CrowdDensityOption)setting.value;
break;
// 14 is missing from settings
@@ -252,23 +254,23 @@ public static GraphicsData Load(string graphicsJson)
// It is meant to be like this because miyoyo
case 16:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Co-Op Teammate Effects: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Co-Op Teammate Effects: {setting.value}", LogType.Debug, true);
#endif
- graphics.CoOpTeammateEffects = (CoOpTeammateEffectsOption)setting["value"];
+ graphics.CoOpTeammateEffects = (CoOpTeammateEffectsOption)setting.value;
break;
case 15:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Subsurface Scattering: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Subsurface Scattering: {setting.value}", LogType.Debug, true);
#endif
- graphics.SubsurfaceScattering = (SubsurfaceScatteringOption)setting["value"];
+ graphics.SubsurfaceScattering = (SubsurfaceScatteringOption)setting.value;
break;
case 17:
#if DEBUG
- LogWriteLine($"Loaded Genshin Settings: Graphics - Anisotropic Filtering: {setting["value"]}", LogType.Debug, true);
+ LogWriteLine($"Loaded Genshin Settings: Graphics - Anisotropic Filtering: {setting.value}", LogType.Debug, true);
#endif
- graphics.AnisotropicFiltering = (AnisotropicFilteringOption)setting["value"];
+ graphics.AnisotropicFiltering = (AnisotropicFilteringOption)setting.value;
break;
}
}
@@ -279,29 +281,37 @@ public string Save()
{
customVolatileGrades = new()
{
- new Dictionary() { { "key", 1 }, { "value", (int)FPS } },
- new Dictionary() { { "key", 2 }, { "value", (int)RenderResolution } },
- new Dictionary() { { "key", 3 }, { "value", (int)ShadowQuality } },
- new Dictionary() { { "key", 4 }, { "value", (int)VisualEffects } },
- new Dictionary() { { "key", 5 }, { "value", (int)SFXQuality } },
- new Dictionary() { { "key", 6 }, { "value", (int)EnvironmentDetail } },
- new Dictionary() { { "key", 7 }, { "value", (int)VerticalSync } },
- new Dictionary() { { "key", 8 }, { "value", (int)Antialiasing } },
- new Dictionary() { { "key", 9 }, { "value", (int)VolumetricFog } },
- new Dictionary() { { "key", 10 }, { "value", (int)Reflections } },
- new Dictionary() { { "key", 11 }, { "value", (int)MotionBlur } },
- new Dictionary() { { "key", 12 }, { "value", (int)Bloom } },
- new Dictionary() { { "key", 13 }, { "value", (int)CrowdDensity } },
- new Dictionary() { { "key", 16 }, { "value", (int)CoOpTeammateEffects } },
- new Dictionary() { { "key", 15 }, { "value", (int)SubsurfaceScattering } },
- new Dictionary() { { "key", 17 }, { "value", (int)AnisotropicFiltering } },
+ new GenshinKeyValuePair(1, (int)FPS),
+ new GenshinKeyValuePair(2, (int)RenderResolution),
+ new GenshinKeyValuePair(3, (int)ShadowQuality),
+ new GenshinKeyValuePair(4, (int)VisualEffects),
+ new GenshinKeyValuePair(5, (int)SFXQuality),
+ new GenshinKeyValuePair(6, (int)EnvironmentDetail),
+ new GenshinKeyValuePair(7, (int)VerticalSync),
+ new GenshinKeyValuePair(8, (int)Antialiasing),
+ new GenshinKeyValuePair(9, (int)VolumetricFog),
+ new GenshinKeyValuePair(10, (int)Reflections),
+ new GenshinKeyValuePair(11, (int)MotionBlur),
+ new GenshinKeyValuePair(12, (int)Bloom),
+ new GenshinKeyValuePair(13, (int)CrowdDensity),
+ new GenshinKeyValuePair(16, (int)CoOpTeammateEffects),
+ new GenshinKeyValuePair(15, (int)SubsurfaceScattering),
+ new GenshinKeyValuePair(17, (int)AnisotropicFiltering)
};
- string data = JsonSerializer.Serialize(this, typeof(GraphicsData), GraphicsDataContext.Default);
+
+ JsonSerializerOptions options = new JsonSerializerOptions()
+ {
+ TypeInfoResolver = GenshinSettingsJSONContext.Default,
+ Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+ };
+
+ string data = JsonSerializer.Serialize(this, typeof(GraphicsData), options);
#if DEBUG
LogWriteLine($"Saved Genshin GraphicsData\r\n{data}", LogType.Debug, true);
#endif
return data;
}
+#nullable disable
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/ScreenManager.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/ScreenManager.cs
index 3d9f0fc6d..8faa4f027 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/ScreenManager.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/RegistryClass/ScreenManager.cs
@@ -5,7 +5,7 @@
using Microsoft.Win32;
using System;
using System.Drawing;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Genshin
@@ -96,8 +96,9 @@ public override bool isfullScreen
};
}
#endregion
-#nullable enable
+
#region Methods
+#nullable enable
public static ScreenManager Load()
{
try
@@ -135,18 +136,12 @@ public override void Save()
try
{
RegistryRoot?.SetValue(_ValueNameScreenManagerFullscreen, fullscreen, RegistryValueKind.DWord);
-#if DEBUG
- LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerFullscreen} : {RegistryRoot.GetValue(_ValueNameScreenManagerFullscreen, null)}", LogType.Debug, true);
-#endif
-
RegistryRoot?.SetValue(_ValueNameScreenManagerWidth, width, RegistryValueKind.DWord);
-#if DEBUG
- LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerWidth} : {RegistryRoot.GetValue(_ValueNameScreenManagerWidth, null)}", LogType.Debug, true);
-#endif
-
RegistryRoot?.SetValue(_ValueNameScreenManagerHeight, height, RegistryValueKind.DWord);
#if DEBUG
- LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerHeight} : {RegistryRoot.GetValue(_ValueNameScreenManagerHeight, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerFullscreen} : {RegistryRoot?.GetValue(_ValueNameScreenManagerFullscreen, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerWidth} : {RegistryRoot?.GetValue(_ValueNameScreenManagerWidth, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved Genshin Settings: {_ValueNameScreenManagerHeight} : {RegistryRoot?.GetValue(_ValueNameScreenManagerHeight, null)}", LogType.Debug, true);
#endif
}
catch (Exception ex)
@@ -155,18 +150,8 @@ public override void Save()
}
}
- public bool Equals(ScreenManager? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.sizeRes == this.sizeRes &&
- comparedTo.height == this.height &&
- comparedTo.width == this.width &&
- comparedTo.fullscreen == this.fullscreen;
- }
- #endregion
+ public bool Equals(ScreenManager? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#nullable disable
-
+ #endregion
}
}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Settings.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Settings.cs
index cba9d337f..728ebb35f 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Settings.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Genshin/Settings.cs
@@ -1,25 +1,23 @@
using CollapseLauncher.GameSettings.Base;
-using CollapseLauncher.GameSettings.Genshin;
using CollapseLauncher.GameSettings.Universal;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
using Microsoft.Win32;
using System.IO;
-using static CollapseLauncher.GameSettings.Statics;
namespace CollapseLauncher.GameSettings.Genshin
{
- internal class GenshinSettings : ImportExportBase, IGameSettings, IGameSettingsUniversal
+ internal class GenshinSettings : SettingsBase, IGameSettings, IGameSettingsUniversal
{
public CustomArgs SettingsCustomArgument { get; set; }
public BaseScreenSettingData SettingsScreen { get; set; }
public CollapseScreenSetting SettingsCollapseScreen { get; set; }
public GeneralData SettingsGeneralData { get; set; }
- public GenshinSettings()
+ public GenshinSettings(IGameVersionCheck GameVersionManager)
+ : base(GameVersionManager)
{
// Init Root Registry Key
- RegistryPath = Path.Combine(RegistryRootPath, PageStatics._GameVersion.GamePreset.InternalGameNameInConfig);
+ RegistryPath = Path.Combine($"Software\\{_gameVersionManager.VendorTypeProp.VendorType}", _gameVersionManager.GamePreset.InternalGameNameInConfig);
RegistryRoot = Registry.CurrentUser.OpenSubKey(RegistryPath, true);
// If the Root Registry Key is null (not exist), then create a new one.
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Context.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Context.cs
index 23ec9b78c..50a418a78 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Context.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Context.cs
@@ -4,22 +4,10 @@
namespace CollapseLauncher.GameSettings.Honkai.Context
{
[JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(ScreenSettingData))]
[JsonSerializable(typeof(PersonalAudioSetting))]
- internal sealed partial class PersonalAudioSettingContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(PersonalAudioSettingVolume))]
- internal sealed partial class PersonalAudioSettingVolumeContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(PersonalGraphicsSettingV2))]
- internal sealed partial class PersonalGraphicsSettingV2Context : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(PersonalAudioSettingVolume))]
[JsonSerializable(typeof(Dictionary))]
- internal sealed partial class D_PersonalGraphicsSettingV2Context : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(ScreenSettingData))]
- internal sealed partial class ScreenSettingDataContext : JsonSerializerContext { }
+ internal sealed partial class HonkaiSettingsJSONContext : JsonSerializerContext { }
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSetting.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSetting.cs
index 8c1bbd98c..fde2678f9 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSetting.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSetting.cs
@@ -6,7 +6,7 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Data.ConverterTool;
using static Hi3Helper.Logger;
@@ -187,7 +187,7 @@ public static PersonalAudioSetting Load()
#if DEBUG
LogWriteLine($"Loaded HI3 Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (PersonalAudioSetting?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalAudioSetting), PersonalAudioSettingContext.Default) ?? new PersonalAudioSetting();
+ return (PersonalAudioSetting?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalAudioSetting), HonkaiSettingsJSONContext.Default) ?? new PersonalAudioSetting();
}
}
catch (Exception ex)
@@ -204,7 +204,7 @@ public void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(PersonalAudioSetting), PersonalAudioSettingContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(PersonalAudioSetting), HonkaiSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -219,23 +219,7 @@ public void Save()
}
}
- public bool Equals(PersonalAudioSetting? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.IsUserDefined == this.IsUserDefined &&
- comparedTo.CVLanguage == this.CVLanguage &&
- comparedTo._userCVLanguage == this._userCVLanguage &&
- comparedTo.BGMVolume == this.BGMVolume &&
- comparedTo.ElfVolume == this.ElfVolume &&
- comparedTo.CGVolumeV2 == this.CGVolumeV2 &&
- comparedTo.MasterVolume == this.MasterVolume &&
- comparedTo.SoundEffectVolume == this.SoundEffectVolume &&
- comparedTo.VoiceVolume == this.VoiceVolume &&
- comparedTo.Mute == this.Mute;
- }
-#nullable disable
+ public bool Equals(PersonalAudioSetting? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSettingVolume.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSettingVolume.cs
index 0dd2c582f..8ab1b3ee9 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSettingVolume.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalAudioSettingVolume.cs
@@ -5,7 +5,7 @@
using System;
using System.Text;
using System.Text.Json;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Honkai
@@ -81,7 +81,7 @@ public static PersonalAudioSettingVolume Load()
#if DEBUG
LogWriteLine($"Loaded HI3 Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (PersonalAudioSettingVolume?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalAudioSettingVolume), PersonalAudioSettingVolumeContext.Default) ?? new PersonalAudioSettingVolume();
+ return (PersonalAudioSettingVolume?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalAudioSettingVolume), HonkaiSettingsJSONContext.Default) ?? new PersonalAudioSettingVolume();
}
}
catch (Exception ex)
@@ -97,7 +97,7 @@ public void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(PersonalAudioSettingVolume), PersonalAudioSettingVolumeContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(PersonalAudioSettingVolume), HonkaiSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -111,20 +111,7 @@ public void Save()
}
}
- public bool Equals(PersonalAudioSettingVolume? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.BGMVolumeValue == this.BGMVolumeValue &&
- comparedTo.CGVolumeValue == this.CGVolumeValue &&
- comparedTo.ElfVolumeValue == this.ElfVolumeValue &&
- comparedTo.SoundEffectVolumeValue == this.SoundEffectVolumeValue &&
- comparedTo.CreateByDefault == this.CreateByDefault &&
- comparedTo.VoiceVolumeValue == this.VoiceVolumeValue &&
- comparedTo.MasterVolumeValue == this.MasterVolumeValue;
- }
-#nullable disable
+ public bool Equals(PersonalAudioSettingVolume? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalGraphicsSettingV2.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalGraphicsSettingV2.cs
index a04519e43..510bcdc86 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalGraphicsSettingV2.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/PersonalGraphicsSettingV2.cs
@@ -7,7 +7,7 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Honkai
@@ -161,7 +161,7 @@ public static PersonalGraphicsSettingV2 Load()
#if DEBUG
LogWriteLine($"Loaded HI3 Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (PersonalGraphicsSettingV2?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalGraphicsSettingV2), PersonalGraphicsSettingV2Context.Default) ?? new PersonalGraphicsSettingV2();
+ return (PersonalGraphicsSettingV2?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PersonalGraphicsSettingV2), HonkaiSettingsJSONContext.Default) ?? new PersonalGraphicsSettingV2();
}
}
catch (Exception ex)
@@ -178,7 +178,7 @@ public void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(PersonalGraphicsSettingV2), PersonalGraphicsSettingV2Context.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(PersonalGraphicsSettingV2), HonkaiSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -192,28 +192,7 @@ public void Save()
}
}
- public bool Equals(PersonalGraphicsSettingV2? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.UseHDR == this.UseHDR &&
- comparedTo.UseFXAA == this.UseFXAA &&
- comparedTo.UsePostFX == this.UsePostFX &&
- comparedTo.ResolutionQuality == this.ResolutionQuality &&
- comparedTo.ReflectionQuality == this.ReflectionQuality &&
- comparedTo.ShadowLevel == this.ShadowLevel &&
- comparedTo.AmbientOcclusion == this.AmbientOcclusion &&
- comparedTo.GlobalIllumination == this.GlobalIllumination &&
- comparedTo.LodGrade == this.LodGrade &&
- comparedTo.PostFXGrade == this.PostFXGrade &&
- comparedTo.TargetFrameRateForInLevel == this.TargetFrameRateForInLevel &&
- comparedTo.TargetFrameRateForOthers == this.TargetFrameRateForOthers &&
- comparedTo.UseDistortion == this.UseDistortion &&
- comparedTo.UseDynamicBone == this.UseDynamicBone &&
- comparedTo.VolumetricLight == this.VolumetricLight;
- }
-#nullable disable
+ public bool Equals(PersonalGraphicsSettingV2? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/Preset.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/Preset.cs
index bdba0a235..bc4a07e26 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/Preset.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/Preset.cs
@@ -7,7 +7,7 @@
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Shared.Region.LauncherConfig;
namespace CollapseLauncher.GameSettings
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/ScreenSettingData.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/ScreenSettingData.cs
index 44d32ec1b..b1a9d66e8 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/ScreenSettingData.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/RegistryClass/ScreenSettingData.cs
@@ -9,7 +9,7 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Honkai
@@ -105,7 +105,7 @@ public static ScreenSettingData Load()
#if DEBUG
LogWriteLine($"Loaded HI3 Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (ScreenSettingData?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(ScreenSettingData), ScreenSettingDataContext.Default) ?? new ScreenSettingData();
+ return (ScreenSettingData?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(ScreenSettingData), HonkaiSettingsJSONContext.Default) ?? new ScreenSettingData();
}
}
catch (Exception ex)
@@ -122,7 +122,7 @@ public override void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(ScreenSettingData), ScreenSettingDataContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(ScreenSettingData), HonkaiSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -144,17 +144,7 @@ private void SaveIndividualRegistry()
RegistryRoot?.SetValue(_ValueNameScreenManagerHeight, height, RegistryValueKind.DWord);
}
- public bool Equals(ScreenSettingData? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.sizeRes == this.sizeRes &&
- comparedTo.height == this.height &&
- comparedTo.width == this.width &&
- comparedTo.isfullScreen == this.isfullScreen;
- }
-#nullable disable
+ public bool Equals(ScreenSettingData? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Settings.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Settings.cs
index 36246b2dd..cb47a5632 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Settings.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Honkai/Settings.cs
@@ -2,18 +2,16 @@
using CollapseLauncher.GameSettings.Honkai.Context;
using CollapseLauncher.GameSettings.Universal;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
using Hi3Helper.Preset;
using Microsoft.Win32;
using System.IO;
-using static CollapseLauncher.GameSettings.Statics;
namespace CollapseLauncher.GameSettings.Honkai
{
- internal class HonkaiSettings : ImportExportBase, IGameSettings, IGameSettingsUniversal
+ internal class HonkaiSettings : SettingsBase, IGameSettings, IGameSettingsUniversal
{
#region PresetProperties
- public Preset Preset_SettingsGraphics { get; set; }
+ public Preset Preset_SettingsGraphics { get; set; }
#endregion
#region SettingProperties
@@ -24,10 +22,11 @@ internal class HonkaiSettings : ImportExportBase, IGameSettings, IGameSettingsUn
public CollapseScreenSetting SettingsCollapseScreen { get; set; }
#endregion
- public HonkaiSettings()
+ public HonkaiSettings(IGameVersionCheck GameVersionManager)
+ : base(GameVersionManager)
{
// Init Root Registry Key
- RegistryPath = Path.Combine(RegistryRootPath, PageStatics._GameVersion.GamePreset.InternalGameNameInConfig);
+ RegistryPath = Path.Combine($"Software\\{_gameVersionManager.VendorTypeProp.VendorType}", _gameVersionManager.GamePreset.InternalGameNameInConfig);
RegistryRoot = Registry.CurrentUser.OpenSubKey(RegistryPath, true);
// If the Root Registry Key is null (not exist), then create a new one.
@@ -50,7 +49,7 @@ private void InitializeSettings()
SettingsCollapseScreen = CollapseScreenSetting.Load();
// Load Preset
- Preset_SettingsGraphics = Preset.LoadPreset(GameType.Honkai, D_PersonalGraphicsSettingV2Context.Default);
+ Preset_SettingsGraphics = Preset.LoadPreset(GameType.Honkai, HonkaiSettingsJSONContext.Default);
}
public void ReloadSettings() => InitializeSettings();
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Context.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Context.cs
index c72a20f2f..0a18f5f6d 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Context.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Context.cs
@@ -5,9 +5,6 @@ namespace CollapseLauncher.GameSettings.StarRail.Context
{
[JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(Model))]
- internal sealed partial class ModelContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(PCResolution))]
- internal sealed partial class PCResolutionContext : JsonSerializerContext { }
+ internal sealed partial class StarRailSettingsJSONContext : JsonSerializerContext { }
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/BGMVolume.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/BGMVolume.cs
index fcf9b1f54..838c22967 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/BGMVolume.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/BGMVolume.cs
@@ -2,10 +2,8 @@
using Hi3Helper;
using Microsoft.Win32;
using System;
-using System.Text;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
-using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CollapseLauncher.GameSettings.StarRail
{
@@ -67,14 +65,7 @@ public void Save()
}
- public bool Equals(BGMVolume? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.BGMVol == this.BGMVol;
- }
-#nullable disable
+ public bool Equals(BGMVolume? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalAudioLanguage.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalAudioLanguage.cs
index 667f813f4..45ec39c56 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalAudioLanguage.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalAudioLanguage.cs
@@ -3,7 +3,7 @@
using Microsoft.Win32;
using System;
using System.Text;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
@@ -93,14 +93,7 @@ public void Save()
}
- public bool Equals(LocalAudioLanguage? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.LocalAudioLang == this.LocalAudioLang;
- }
-#nullable disable
+ public bool Equals(LocalAudioLanguage? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalTextLanguage.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalTextLanguage.cs
index 69f1c5110..b96af6202 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalTextLanguage.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/LocalTextLanguage.cs
@@ -3,7 +3,7 @@
using Microsoft.Win32;
using System;
using System.Text;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
@@ -112,14 +112,7 @@ public void Save()
}
- public bool Equals(LocalTextLanguage? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.LocalTextLang == this.LocalTextLang;
- }
-#nullable disable
+ public bool Equals(LocalTextLanguage? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/MasterVolume.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/MasterVolume.cs
index f7b097b77..f340c99e7 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/MasterVolume.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/MasterVolume.cs
@@ -2,7 +2,7 @@
using Hi3Helper;
using Microsoft.Win32;
using System;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.StarRail
@@ -65,14 +65,7 @@ public void Save()
}
- public bool Equals(MasterVolume? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.MasterVol == this.MasterVol;
- }
-#nullable disable
+ public bool Equals(MasterVolume? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/Model.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/Model.cs
index 68d4f904b..feb18977c 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/Model.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/Model.cs
@@ -1,13 +1,12 @@
using CollapseLauncher.GameSettings.StarRail.Context;
using CollapseLauncher.Interfaces;
-using Google.Protobuf.WellKnownTypes;
using Hi3Helper;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.StarRail
@@ -30,7 +29,7 @@ public enum AntialiasingMode // TypeDefIndex: 25409
TAA = 1,
FXAA = 2
}
-#endregion
+ #endregion
internal class Model : IGameSettingsValue
{
@@ -114,6 +113,13 @@ private static Dictionary GenerateStaticFPSIndexDict()
///
public Quality ReflectionQuality { get; set; } = Quality.Medium;
+ ///
+ /// This defines "SFX Quality " combobox In-game settings. >
+ /// Options: VeryLow (1), Low (2), Medium(3), High(4)
+ /// Default: Medium
+ ///
+ public Quality SFXQuality { get; set; } = Quality.Medium;
+
///
/// This defines "Bloom Quality " combobox In-game settings.
/// Options: Off(0), VeryLow (1), Low (2), Medium(3), High(4), VeryHigh(5)
@@ -145,7 +151,7 @@ public static Model Load()
#if DEBUG
LogWriteLine($"Loaded StarRail Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (Model?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(Model), ModelContext.Default) ?? new Model();
+ return (Model?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(Model), StarRailSettingsJSONContext.Default) ?? new Model();
}
}
catch (Exception ex)
@@ -162,7 +168,7 @@ public void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(Model), ModelContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(Model), StarRailSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
#if DEBUG
@@ -174,24 +180,8 @@ public void Save()
LogWriteLine($"Failed to save {_ValueName}!\r\n{ex}", LogType.Error, true);
}
}
- public bool Equals(Model? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.AAMode == this.AAMode &&
- comparedTo.ShadowQuality == this.ShadowQuality &&
- comparedTo.LightQuality == this.LightQuality &&
- comparedTo.CharacterQuality == this.CharacterQuality &&
- comparedTo.BloomQuality == this.BloomQuality &&
- comparedTo.EnvDetailQuality == this.EnvDetailQuality &&
- comparedTo.ReflectionQuality == this.ReflectionQuality &&
- comparedTo.FPS == this.FPS &&
- comparedTo.EnableVSync == this.EnableVSync &&
- comparedTo.RenderScale == this.RenderScale &&
- comparedTo.ResolutionQuality == this.ResolutionQuality;
-#nullable disable
- }
+
+ public bool Equals(Model? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/PCResolution.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/PCResolution.cs
index e13e75337..0b5c1ca91 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/PCResolution.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/PCResolution.cs
@@ -9,9 +9,8 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
-using static System.Runtime.InteropServices.JavaScript.JSType;
namespace CollapseLauncher.GameSettings.StarRail
{
@@ -106,7 +105,7 @@ public static PCResolution Load()
#if DEBUG
LogWriteLine($"Loaded StarRail Settings: {_ValueName}\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (PCResolution?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PCResolution), PCResolutionContext.Default) ?? new PCResolution();
+ return (PCResolution?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(PCResolution), StarRailSettingsJSONContext.Default) ?? new PCResolution();
}
}
catch (Exception ex)
@@ -123,7 +122,7 @@ public override void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(PCResolution), PCResolutionContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(PCResolution), StarRailSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
RegistryRoot.SetValue(_ValueName, dataByte, RegistryValueKind.Binary);
@@ -144,23 +143,13 @@ private void SaveIndividualRegistry()
RegistryRoot?.SetValue(_ValueNameScreenManagerWidth, width, RegistryValueKind.DWord);
RegistryRoot?.SetValue(_ValueNameScreenManagerHeight, height, RegistryValueKind.DWord);
#if DEBUG
- LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerFullscreen} : {RegistryRoot.GetValue(_ValueNameScreenManagerFullscreen, null)}", LogType.Debug, true);
- LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerWidth} : {RegistryRoot.GetValue(_ValueNameScreenManagerWidth, null)}", LogType.Debug, true);
- LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerHeight} : {RegistryRoot.GetValue(_ValueNameScreenManagerHeight, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerFullscreen} : {RegistryRoot?.GetValue(_ValueNameScreenManagerFullscreen, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerWidth} : {RegistryRoot?.GetValue(_ValueNameScreenManagerWidth, null)}", LogType.Debug, true);
+ LogWriteLine($"Saved StarRail Settings: {_ValueNameScreenManagerHeight} : {RegistryRoot?.GetValue(_ValueNameScreenManagerHeight, null)}", LogType.Debug, true);
#endif
}
- public bool Equals(PCResolution? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.sizeRes == this.sizeRes &&
- comparedTo.height == this.height &&
- comparedTo.width == this.width &&
- comparedTo.isfullScreen == this.isfullScreen;
- }
-#nullable disable
+ public bool Equals(PCResolution? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
\ No newline at end of file
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/SFXVolume.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/SFXVolume.cs
index 88ad24acd..a7ec102c7 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/SFXVolume.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/SFXVolume.cs
@@ -2,7 +2,7 @@
using Hi3Helper;
using Microsoft.Win32;
using System;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.StarRail
@@ -65,14 +65,7 @@ public void Save()
}
- public bool Equals(SFXVolume? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.SFXVol == this.SFXVol;
- }
-#nullable disable
+ public bool Equals(SFXVolume? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/VOVolume.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/VOVolume.cs
index ae446e68c..1fdf96a0e 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/VOVolume.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/RegistryClass/VOVolume.cs
@@ -2,7 +2,7 @@
using Hi3Helper;
using Microsoft.Win32;
using System;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.StarRail
@@ -65,14 +65,7 @@ public void Save()
}
- public bool Equals(VOVolume? comparedTo)
- {
- if (ReferenceEquals(this, comparedTo)) return true;
- if (comparedTo == null) return false;
-
- return comparedTo.VOVol == this.VOVol;
- }
-#nullable disable
+ public bool Equals(VOVolume? comparedTo) => TypeExtensions.IsInstancePropertyEqual(this, comparedTo);
#endregion
}
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Settings.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Settings.cs
index 7101a80ee..111947f86 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Settings.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/StarRail/Settings.cs
@@ -1,14 +1,12 @@
using CollapseLauncher.GameSettings.Base;
using CollapseLauncher.GameSettings.Universal;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
using Microsoft.Win32;
using System.IO;
-using static CollapseLauncher.GameSettings.Statics;
namespace CollapseLauncher.GameSettings.StarRail
{
- internal class StarRailSettings : ImportExportBase, IGameSettings, IGameSettingsUniversal
+ internal class StarRailSettings : SettingsBase, IGameSettings, IGameSettingsUniversal
{
public CustomArgs SettingsCustomArgument { get; set; }
public BaseScreenSettingData SettingsScreen { get; set; }
@@ -18,13 +16,14 @@ internal class StarRailSettings : ImportExportBase, IGameSettings, IGameSettings
public MasterVolume AudioSettings_Master { get; set; }
public SFXVolume AudioSettings_SFX { get; set; }
public VOVolume AudioSettings_VO { get; set; }
- public LocalAudioLanguage AudioLanguage { get; set; }
+ public LocalAudioLanguage AudioLanguage { get; set; }
public LocalTextLanguage TextLanguage { get; set; }
- public StarRailSettings()
+ public StarRailSettings(IGameVersionCheck GameVersionManager)
+ : base(GameVersionManager)
{
// Init Root Registry Key
- RegistryPath = Path.Combine(RegistryRootPath, PageStatics._GameVersion.GamePreset.InternalGameNameInConfig);
+ RegistryPath = Path.Combine($"Software\\{_gameVersionManager.VendorTypeProp.VendorType}", _gameVersionManager.GamePreset.InternalGameNameInConfig);
RegistryRoot = Registry.CurrentUser.OpenSubKey(RegistryPath, true);
// If the Root Registry Key is null (not exist), then create a new one.
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Statics.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Statics.cs
deleted file mode 100644
index 28005eed4..000000000
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Statics.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using CollapseLauncher.Statics;
-using Microsoft.Win32;
-
-namespace CollapseLauncher.GameSettings
-{
- internal static class Statics
- {
-#nullable enable
- internal static string RegistryRootPath { get => $"Software\\{PageStatics._GameVersion.VendorTypeProp.VendorType}"; }
- internal static string? RegistryPath;
- internal static RegistryKey? RegistryRoot;
-#nullable disable
- }
-}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/Context.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/Context.cs
index 2e1f7c6cd..339f907bd 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/Context.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/Context.cs
@@ -4,5 +4,5 @@ namespace CollapseLauncher.GameSettings.Universal
{
[JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(CollapseScreenSetting))]
- internal sealed partial class CollapseScreenSettingContext : JsonSerializerContext { }
+ internal sealed partial class UniversalSettingsJSONContext : JsonSerializerContext { }
}
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CollapseScreenSetting.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CollapseScreenSetting.cs
index 684b94869..3d0cabee1 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CollapseScreenSetting.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CollapseScreenSetting.cs
@@ -4,7 +4,7 @@
using System;
using System.Text;
using System.Text.Json;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.GameSettings.Base.SettingsBase;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Universal
@@ -17,17 +17,23 @@ internal class CollapseScreenSetting : IGameSettingsValue
#region Properties
///
- /// This defines if the game will be running in a custom resolution.
+ /// This defines if the game should run in a custom resolution.
/// Default: false
///
public bool UseCustomResolution { get; set; } = false;
///
- /// This defines if the game will be running in Exclusive Fullscreen mode.
+ /// This defines if the game should run in Exclusive Fullscreen mode.
/// Default: false
///
public bool UseExclusiveFullscreen { get; set; } = false;
+ ///
+ /// This defines if the game should run in Borderless Screen mode.
+ /// Default: false
+ ///
+ public bool UseBorderlessScreen { get; set; } = false;
+
///
/// This defines the Graphics API will be used for the game to run.
/// Values:
@@ -57,7 +63,7 @@ public static CollapseScreenSetting Load()
#if DEBUG
LogWriteLine($"Loaded Collapse Screen Settings:\r\n{Encoding.UTF8.GetString((byte[])value, 0, ((byte[])value).Length - 1)}", LogType.Debug, true);
#endif
- return (CollapseScreenSetting?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(CollapseScreenSetting), CollapseScreenSettingContext.Default) ?? new CollapseScreenSetting();
+ return (CollapseScreenSetting?)JsonSerializer.Deserialize(byteStr.Slice(0, byteStr.Length - 1), typeof(CollapseScreenSetting), UniversalSettingsJSONContext.Default) ?? new CollapseScreenSetting();
}
}
catch (Exception ex)
@@ -74,7 +80,7 @@ public void Save()
{
if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
- string data = JsonSerializer.Serialize(this, typeof(CollapseScreenSetting), CollapseScreenSettingContext.Default) + '\0';
+ string data = JsonSerializer.Serialize(this, typeof(CollapseScreenSetting), UniversalSettingsJSONContext.Default) + '\0';
byte[] dataByte = Encoding.UTF8.GetBytes(data);
#if DEBUG
LogWriteLine($"Saved Collapse Screen Settings:\r\n{data}", LogType.Debug, true);
diff --git a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CustomArgs.cs b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CustomArgs.cs
index 310efd6c0..1381ac911 100644
--- a/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CustomArgs.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameSettings/Universal/RegistryClass/CustomArgs.cs
@@ -1,8 +1,8 @@
-using CollapseLauncher.Interfaces;
+using CollapseLauncher.GameSettings.Base;
+using CollapseLauncher.Interfaces;
using Hi3Helper;
using Microsoft.Win32;
using System;
-using static CollapseLauncher.GameSettings.Statics;
using static Hi3Helper.Logger;
namespace CollapseLauncher.GameSettings.Universal
@@ -35,11 +35,11 @@ public static CustomArgs Load()
{
try
{
- if (RegistryRoot == null) throw new NullReferenceException($"Cannot load {_ValueName} RegistryKey is unexpectedly not initialized!");
+ if (SettingsBase.RegistryRoot == null) throw new NullReferenceException($"Cannot load {_ValueName} RegistryKey is unexpectedly not initialized!");
#if DEBUG
- LogWriteLine($"Loaded Collapse Custom Argument Settings:\r\n{(string?)RegistryRoot.GetValue(_ValueName, null) ?? ""}", LogType.Debug, true);
+ LogWriteLine($"Loaded Collapse Custom Argument Settings:\r\n{(string?)SettingsBase.RegistryRoot.GetValue(_ValueName, null) ?? ""}", LogType.Debug, true);
#endif
- return new CustomArgs { CustomArgumentValue = (string?)RegistryRoot.GetValue(_ValueName, null) ?? "" };
+ return new CustomArgs { CustomArgumentValue = (string?)SettingsBase.RegistryRoot.GetValue(_ValueName, null) ?? "" };
}
catch (Exception ex)
{
@@ -52,11 +52,11 @@ public void Save()
{
try
{
- if (RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
+ if (SettingsBase.RegistryRoot == null) throw new NullReferenceException($"Cannot save {_ValueName} since RegistryKey is unexpectedly not initialized!");
#if DEBUG
LogWriteLine($"Saved Collapse Custom Argument Settings:\r\n{CustomArgumentValue}", LogType.Debug, true);
#endif
- RegistryRoot.SetValue(_ValueName, CustomArgumentValue, RegistryValueKind.String);
+ SettingsBase.RegistryRoot.SetValue(_ValueName, CustomArgumentValue, RegistryValueKind.String);
}
catch (Exception ex)
{
diff --git a/CollapseLauncher/Classes/GameManagement/GameVersion/BaseClass/GameVersionBase.cs b/CollapseLauncher/Classes/GameManagement/GameVersion/BaseClass/GameVersionBase.cs
index e1fd6a84a..df4e2f875 100644
--- a/CollapseLauncher/Classes/GameManagement/GameVersion/BaseClass/GameVersionBase.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameVersion/BaseClass/GameVersionBase.cs
@@ -217,7 +217,6 @@ public virtual bool IsGameInstalled()
// Check if the executable file exist and has the size at least > 2 MiB. If not, then return as false.
FileInfo execFileInfo = new FileInfo(Path.Combine(GameDirPath, GamePreset.GameExecutableName));
- if (execFileInfo.Exists) return execFileInfo.Length > 1 << 16;
// Check if the vendor type exist. If not, then return false
if (VendorTypeProp.GameName == null || !VendorTypeProp.VendorType.HasValue) return false;
@@ -300,7 +299,7 @@ private GameVersion TryGetNextVersionFromPkgFileName(RegionResourceVersion pkgVe
// Set the offset of the section. If the length > 2, then set 1
// Otherwise, set 2;
- int offset = pkgSections.Length > 2 ? 2 : 1;
+ int offset = pkgSections.Length > 2 ? 1 : 2;
// Try get the version string, lower it and trim it
string versionStr = pkgSections[offset].ToLower().Trim('v');
diff --git a/CollapseLauncher/Classes/GameManagement/GameVersion/Genshin/VersionCheck.cs b/CollapseLauncher/Classes/GameManagement/GameVersion/Genshin/VersionCheck.cs
index d13348a1f..7a3d94770 100644
--- a/CollapseLauncher/Classes/GameManagement/GameVersion/Genshin/VersionCheck.cs
+++ b/CollapseLauncher/Classes/GameManagement/GameVersion/Genshin/VersionCheck.cs
@@ -3,7 +3,6 @@
using Hi3Helper.Shared.ClassStruct;
using Microsoft.UI.Xaml;
using System.Collections.Generic;
-using System.Linq;
namespace CollapseLauncher.GameVersioning
{
diff --git a/CollapseLauncher/Classes/InstallManagement/BaseClass/GameInstallPackage.cs b/CollapseLauncher/Classes/InstallManagement/BaseClass/GameInstallPackage.cs
index eded01dba..3095ab5b3 100644
--- a/CollapseLauncher/Classes/InstallManagement/BaseClass/GameInstallPackage.cs
+++ b/CollapseLauncher/Classes/InstallManagement/BaseClass/GameInstallPackage.cs
@@ -70,11 +70,35 @@ public GameInstallPackage(RegionResourceVersion packageProperty, string pathOutp
}
}
+ public bool IsReadStreamExist(int count)
+ {
+ // Check if the single file exist or not
+ FileInfo fileInfo = new FileInfo(PathOutput);
+ if (fileInfo.Exists)
+ return true;
+
+ // Check for the chunk files
+ return Enumerable.Range(0, count).All(chunkID =>
+ {
+ // Get the hash number
+ long ID = Http.GetHashNumber(count, chunkID);
+ // Append the hash number to the path
+ string path = $"{PathOutput}.{ID}";
+ // Get the file info
+ FileInfo fileInfo = new FileInfo(path);
+ // Check if the file exist
+ return fileInfo.Exists;
+ });
+ }
+
public Stream GetReadStream(int count)
{
+ // Get the file info of the single file
FileInfo fileInfo = new FileInfo(PathOutput);
+ // Check if the file exist and the length is equal to the size
if (fileInfo.Exists && fileInfo.Length == Size)
{
+ // Return the stream for read
return fileInfo.Open(new FileStreamOptions
{
Access = FileAccess.Read,
@@ -85,6 +109,7 @@ public Stream GetReadStream(int count)
});
}
+ // If the single file doesn't exist, then try getting chunk stream
return GetCombinedStreamFromPackageAsset(count);
}
@@ -119,14 +144,20 @@ public void DeleteFile(int count)
private CombinedStream GetCombinedStreamFromPackageAsset(int count)
{
+ // Set the array
FileStream[] streamList = new FileStream[count];
+ // Enumerate the ID
for (int i = 0; i < streamList.Length; i++)
{
+ // Get the hash ID
long ID = Http.GetHashNumber(count, i);
+ // Append hash ID to the path
string path = $"{PathOutput}.{ID}";
+ // Get the file info and check if the file exist
FileInfo fileInfo = new FileInfo(path);
if (fileInfo.Exists)
{
+ // Allocate to the array and open the stream
streamList[i] = fileInfo.Open(new FileStreamOptions
{
Access = FileAccess.Read,
@@ -135,12 +166,15 @@ private CombinedStream GetCombinedStreamFromPackageAsset(int count)
Options = FileOptions.None,
Share = FileShare.Read
});
+ // Then go back to the loop routine
continue;
}
+ // If not found, then throw
throw new FileNotFoundException($"File chunk doesn't exist in this path! -> {path}");
}
+ // Assign the array and initiate it as a combined stream
return new CombinedStream(streamList);
}
diff --git a/CollapseLauncher/Classes/InstallManagement/BaseClass/InstallManagerBase.cs b/CollapseLauncher/Classes/InstallManagement/BaseClass/InstallManagerBase.cs
index f2a68b4a0..8d274db71 100644
--- a/CollapseLauncher/Classes/InstallManagement/BaseClass/InstallManagerBase.cs
+++ b/CollapseLauncher/Classes/InstallManagement/BaseClass/InstallManagerBase.cs
@@ -1,4 +1,4 @@
-using CollapseLauncher.Interfaces;
+using CollapseLauncher.Interfaces;
using CollapseLauncher.Statics;
using Hi3Helper;
using Hi3Helper.Data;
@@ -33,7 +33,6 @@ internal class InstallManagerBase : ProgressBase (T)PageStatics._GameVersion; }
protected RegionResourceGame _gameRegion { get => _gameVersionManager.GameAPIProp.data; }
protected GameVersion _gameLatestVersion { get => _gameVersionManager.GetGameVersionAPI(); }
protected GameVersion? _gameLatestPreloadVersion { get => _gameVersionManager.GetGameVersionAPIPreload(); }
@@ -46,6 +45,7 @@ internal class InstallManagerBase : ProgressBase !File.Exists(Path.Combine(_gamePath, "@NoDeleteZip")); }
protected bool _canSkipVerif { get => File.Exists(Path.Combine(_gamePath, "@NoVerification")); }
protected bool _canSkipExtract { get => File.Exists(Path.Combine(_gamePath, "@NoExtraction")); }
+ protected bool _canMergeDownloadChunks { get => LauncherConfig.GetAppConfigValue("UseDownloadChunksMerging").ToBool(); }
protected virtual bool _canDeltaPatch { get => false; }
protected virtual DeltaPatchProperty _gameDeltaPatchProperty { get => null; }
@@ -53,14 +53,17 @@ internal class InstallManagerBase : ProgressBase Dispose();
@@ -72,6 +75,7 @@ public void Dispose()
_httpClient?.Dispose();
_gameRepairTool?.Dispose();
_token?.Cancel();
+ IsRunning = false;
Flush();
}
@@ -79,6 +83,7 @@ public virtual void Flush()
{
_gameRepairTool?.Dispose();
_assetIndex.Clear();
+ UpdateCompletenessStatus(CompletenessStatus.Idle);
}
#region Public Methods
@@ -107,48 +112,59 @@ public virtual async ValueTask GetInstallationPath()
public virtual async Task StartPackageDownload(bool skipDialog)
{
+ UpdateCompletenessStatus(CompletenessStatus.Running);
ResetToken();
// Get the game state and run the action for each of them
GameInstallStateEnum gameState = _gameVersionManager.GetGameState();
LogWriteLine($"Gathering packages information for installation (State: {gameState})...", LogType.Default, true);
- switch (gameState)
+ try
{
- case GameInstallStateEnum.NotInstalled:
- case GameInstallStateEnum.GameBroken:
- case GameInstallStateEnum.NeedsUpdate:
- await GetLatestPackageList(_assetIndex, gameState, false);
- break;
- case GameInstallStateEnum.InstalledHavePreload:
- await GetLatestPackageList(_assetIndex, gameState, true);
- break;
- }
+ switch (gameState)
+ {
+ case GameInstallStateEnum.NotInstalled:
+ case GameInstallStateEnum.GameBroken:
+ case GameInstallStateEnum.NeedsUpdate:
+ await GetLatestPackageList(_assetIndex, gameState, false);
+ break;
+ case GameInstallStateEnum.InstalledHavePreload:
+ await GetLatestPackageList(_assetIndex, gameState, true);
+ break;
+ }
- // Set the progress bar to indetermined
- _status.IsIncludePerFileIndicator = _assetIndex.Sum(x => x.Segments != null ? x.Segments.Count : 1) > 1;
- _status.IsProgressPerFileIndetermined = true;
- _status.IsProgressTotalIndetermined = true;
- UpdateStatus();
+ // Set the progress bar to indetermined
+ _status.IsIncludePerFileIndicator = _assetIndex.Sum(x => x.Segments != null ? x.Segments.Count : 1) > 1;
+ _status.IsProgressPerFileIndetermined = true;
+ _status.IsProgressTotalIndetermined = true;
+ UpdateStatus();
- // Start getting the size of the packages
- await GetPackagesRemoteSize(_assetIndex, _token.Token);
+ // Start getting the size of the packages
+ await GetPackagesRemoteSize(_assetIndex, _token.Token);
+
+ // Get the remote total size and current total size
+ _progressTotalSize = _assetIndex.Sum(x => x.Size);
+ _progressTotalSizeCurrent = GetExistingDownloadPackageSize(_assetIndex);
- // Get the remote total size and current total size
- _progressTotalSize = _assetIndex.Sum(x => x.Size);
- _progressTotalSizeCurrent = GetExistingDownloadPackageSize(_assetIndex);
+ // Sanitize Check: Check for the free space of the drive and show the dialog if necessary
+ await CheckDriveFreeSpace(_parentUI, _assetIndex);
+
+ // Sanitize Check: Show dialog for resuming/reset the existing download
+ if (!skipDialog)
+ {
+ await CheckExistingDownloadAsync(_parentUI, _assetIndex);
+ }
- // Sanitize Check: Check for the free space of the drive and show the dialog if necessary
- await CheckDriveFreeSpace(_parentUI, _assetIndex);
+ // Start downloading process
+ await InvokePackageDownloadRoutine(_assetIndex, _token.Token);
- // Sanitize Check: Show dialog for resuming/reset the existing download
- if (!skipDialog)
+ UpdateCompletenessStatus(CompletenessStatus.Completed);
+ }
+ catch
{
- await CheckExistingDownloadAsync(_parentUI, _assetIndex);
+ UpdateCompletenessStatus(CompletenessStatus.Cancelled);
+ throw;
}
-
- // Start downloading process
- await InvokePackageDownloadRoutine(_assetIndex, _token.Token);
}
// Bool: 0 -> Indicates that one of the package is failing and need to redownload
@@ -157,54 +173,65 @@ public virtual async Task StartPackageDownload(bool skipDialog)
// -1 -> Cancel the operation
public virtual async ValueTask StartPackageVerification()
{
- // Get the total asset count
- int assetCount = _assetIndex.Sum(x => x.Segments != null ? x.Segments.Count : 1);
-
- // If the assetIndex is empty, then skip and return 0
- if (assetCount == 0)
+ try
{
- return 0;
- }
+ UpdateCompletenessStatus(CompletenessStatus.Running);
- // If _canSkipVerif flag is true, then return 1 (skip) the verification;
- if (_canSkipVerif) return 1;
+ // Get the total asset count
+ int assetCount = _assetIndex.Sum(x => x.Segments != null ? x.Segments.Count : 1);
- // Set progress count to beginning
- _progressTotalSize = _assetIndex.Sum(x => x.Size);
- _progressTotalSizeCurrent = 0;
- _progressTotalCountCurrent = 1;
- _progressTotalCount = assetCount;
- _status.IsIncludePerFileIndicator = assetCount > 1;
- RestartStopwatch();
+ // If the assetIndex is empty, then skip and return 0
+ if (assetCount == 0)
+ {
+ return 0;
+ }
- // Set progress bar to not indetermined
- _status.IsProgressPerFileIndetermined = false;
- _status.IsProgressTotalIndetermined = false;
+ // If _canSkipVerif flag is true, then return 1 (skip) the verification;
+ if (_canSkipVerif) return 1;
- // Iterate the asset
- foreach (GameInstallPackage asset in _assetIndex)
- {
- int returnCode = 0;
+ // Set progress count to beginning
+ _progressTotalSize = _assetIndex.Sum(x => x.Size);
+ _progressTotalSizeCurrent = 0;
+ _progressTotalCountCurrent = 1;
+ _progressTotalCount = assetCount;
+ _status.IsIncludePerFileIndicator = assetCount > 1;
+ RestartStopwatch();
- // Iterate if the package has segment
- if (asset.Segments != null)
+ // Set progress bar to not indetermined
+ _status.IsProgressPerFileIndetermined = false;
+ _status.IsProgressTotalIndetermined = false;
+
+ // Iterate the asset
+ foreach (GameInstallPackage asset in _assetIndex)
{
- for (int i = 0; i < asset.Segments.Count; i++)
+ int returnCode = 0;
+
+ // Iterate if the package has segment
+ if (asset.Segments != null)
{
- // Run the package verification routine
- if ((returnCode = await RunPackageVerificationRoutine(asset.Segments[i], _token.Token)) < 1)
+ for (int i = 0; i < asset.Segments.Count; i++)
{
- return returnCode;
+ // Run the package verification routine
+ if ((returnCode = await RunPackageVerificationRoutine(asset.Segments[i], _token.Token)) < 1)
+ {
+ return returnCode;
+ }
}
+ continue;
}
- continue;
- }
- // Run the package verification routine as a single package
- if ((returnCode = await RunPackageVerificationRoutine(asset, _token.Token)) < 1)
- {
- return returnCode;
+ // Run the package verification routine as a single package
+ if ((returnCode = await RunPackageVerificationRoutine(asset, _token.Token)) < 1)
+ {
+ return returnCode;
+ }
}
+ UpdateCompletenessStatus(CompletenessStatus.Completed);
+ }
+ catch
+ {
+ UpdateCompletenessStatus(CompletenessStatus.Cancelled);
+ throw;
}
return 1;
@@ -277,92 +304,110 @@ private void DeleteSingleOrSegmentedDownloadStream(GameInstallPackage asset)
asset.DeleteFile(_downloadThreadCount);
}
- public virtual async Task StartPackageInstallation() => await Task.Run(StartPackageInstallationInner, _token.Token);
-
- public void StartPackageInstallationInner()
+ public async Task StartPackageInstallation()
{
- // Sanity Check: Check if the package list is empty or not
- if (_assetIndex.Count == 0) throw new InvalidOperationException("Package list is empty. Make sure you have ran StartPackageDownload() first.");
-
- // If _canSkipExtract flag is true, then return (skip) the extraction
- if (_canSkipExtract) return;
+ try
+ {
+ UpdateCompletenessStatus(CompletenessStatus.Running);
- // Start Async Thread
- // Since the SevenZipTool (especially with the callbacks) can't run under
- // different thread, so the async call will be called at the start
+ await StartPackageInstallationInner();
- // Initialize the zip tool
- using (SevenZipTool zip = new SevenZipTool())
+ UpdateCompletenessStatus(CompletenessStatus.Completed);
+ }
+ catch
{
- // Get the sum of uncompressed size and
- // Set progress count to beginning
- _progressTotalSize = GetAssetIndexTotalUncompressSize(zip, _assetIndex);
+ UpdateCompletenessStatus(CompletenessStatus.Cancelled);
+ throw;
+ }
+ }
- _progressTotalSizeCurrent = 0;
- _progressTotalCountCurrent = 1;
- _progressTotalCount = _assetIndex.Count;
- _status.IsIncludePerFileIndicator = _assetIndex.Count > 1;
- RestartStopwatch();
+ protected virtual async Task StartPackageInstallationInner()
+ {
+ await Task.Run(() =>
+ {
+ // Sanity Check: Check if the package list is empty or not
+ if (_assetIndex.Count == 0) throw new InvalidOperationException("Package list is empty. Make sure you have ran StartPackageDownload() first.");
- // Reset the last size counter
- _totalLastSizeCurrent = 0;
+ // If _canSkipExtract flag is true, then return (skip) the extraction
+ if (_canSkipExtract) return;
- // Try unassign read-only and redundant diff files
- TryUnassignReadOnlyFiles();
- TryRemoveRedundantHDiffList();
+ // Start Async Thread
+ // Since the SevenZipTool (especially with the callbacks) can't run under
+ // different thread, so the async call will be called at the start
- foreach (GameInstallPackage asset in _assetIndex)
+ // Initialize the zip tool
+ using (SevenZipTool zip = new SevenZipTool())
{
- // Update the status
- _status.ActivityStatus = string.Format("{0}: {1}", Lang._Misc.Extracting, string.Format(Lang._Misc.PerFromTo, _progressTotalCountCurrent, _progressTotalCount));
- _status.IsProgressPerFileIndetermined = false;
- _status.IsProgressTotalIndetermined = false;
- UpdateStatus();
+ // Get the sum of uncompressed size and
+ // Set progress count to beginning
+ _progressTotalSize = GetAssetIndexTotalUncompressSize(zip, _assetIndex);
- try
- {
- // Load the zip
- zip.LoadArchive(GetSingleOrSegmentedDownloadStream(asset));
+ _progressTotalSizeCurrent = 0;
+ _progressTotalCountCurrent = 1;
+ _progressTotalCount = _assetIndex.Count;
+ _status.IsIncludePerFileIndicator = _assetIndex.Count > 1;
+ RestartStopwatch();
- // Start extraction
- zip.ExtractProgressChanged += ZipProgressAdapter;
- zip.ExtractToDirectory(_gamePath, _threadCount, _token.Token);
+ // Reset the last size counter
+ _totalLastSizeCurrent = 0;
- // Get the information about diff and delete list file
- FileInfo hdiffList = new FileInfo(Path.Combine(_gamePath, "hdifffiles.txt"));
- FileInfo deleteList = new FileInfo(Path.Combine(_gamePath, "deletefiles.txt"));
+ // Try unassign read-only and redundant diff files
+ TryUnassignReadOnlyFiles();
+ TryRemoveRedundantHDiffList();
- // If diff list file exist, then rename the file
- if (hdiffList.Exists)
- {
- hdiffList.MoveTo(Path.Combine(_gamePath, $"hdifffiles_{Path.GetFileNameWithoutExtension(asset.PathOutput)}.txt"), true);
- }
+ foreach (GameInstallPackage asset in _assetIndex)
+ {
+ // Update the status
+ _status.ActivityStatus = string.Format("{0}: {1}", Lang._Misc.Extracting, string.Format(Lang._Misc.PerFromTo, _progressTotalCountCurrent, _progressTotalCount));
+ _status.IsProgressPerFileIndetermined = false;
+ _status.IsProgressTotalIndetermined = false;
+ UpdateStatus();
- // If the delete zip file exist, then rename the file
- if (deleteList.Exists)
+ try
{
- deleteList.MoveTo(Path.Combine(_gamePath, $"deletefiles_{Path.GetFileNameWithoutExtension(asset.PathOutput)}.txt"), true);
- }
+ // Load the zip
+ zip.LoadArchive(GetSingleOrSegmentedDownloadStream(asset));
+
+ // Start extraction
+ zip.ExtractProgressChanged += ZipProgressAdapter;
+ zip.ExtractToDirectory(_gamePath, _threadCount, _token.Token);
+
+ // Get the information about diff and delete list file
+ FileInfo hdiffList = new FileInfo(Path.Combine(_gamePath, "hdifffiles.txt"));
+ FileInfo deleteList = new FileInfo(Path.Combine(_gamePath, "deletefiles.txt"));
+
+ // If diff list file exist, then rename the file
+ if (hdiffList.Exists)
+ {
+ hdiffList.MoveTo(Path.Combine(_gamePath, $"hdifffiles_{Path.GetFileNameWithoutExtension(asset.PathOutput)}.txt"), true);
+ }
+
+ // If the delete zip file exist, then rename the file
+ if (deleteList.Exists)
+ {
+ deleteList.MoveTo(Path.Combine(_gamePath, $"deletefiles_{Path.GetFileNameWithoutExtension(asset.PathOutput)}.txt"), true);
+ }
- // Make sure that the ZipTool is getting disposed first
- zip?.Dispose();
+ // Make sure that the ZipTool is getting disposed first
+ zip?.Dispose();
- // If the _canDeleteZip flag is true, then delete the zip
- if (_canDeleteZip)
+ // If the _canDeleteZip flag is true, then delete the zip
+ if (_canDeleteZip)
+ {
+ DeleteSingleOrSegmentedDownloadStream(asset);
+ }
+ }
+ catch (Exception) { throw; }
+ finally
{
- DeleteSingleOrSegmentedDownloadStream(asset);
+ zip.ExtractProgressChanged -= ZipProgressAdapter;
+ zip?.Dispose();
}
- }
- catch (Exception) { throw; }
- finally
- {
- zip.ExtractProgressChanged -= ZipProgressAdapter;
- zip?.Dispose();
- }
- _progressTotalCountCurrent++;
+ _progressTotalCountCurrent++;
+ }
}
- }
+ });
}
public virtual async Task StartPostInstallVerification()
@@ -380,35 +425,52 @@ public virtual void ApplyGameConfig(bool forceUpdateToLatest = false)
}
- public virtual bool IsPreloadCompleted()
+ public virtual async ValueTask IsPreloadCompleted()
{
- GetLatestPackageList(_assetIndex, GameInstallStateEnum.InstalledHavePreload, true).Wait();
- bool resultSlice = false, resultZip=false;
- foreach (GameInstallPackage asset in _assetIndex)
+ // Get the latest package list and await
+ await GetLatestPackageList(_assetIndex, GameInstallStateEnum.InstalledHavePreload, true);
+ // Get the total size of the packages
+ await GetPackagesRemoteSize(_assetIndex, _token.Token);
+ long totalPackageSize = _assetIndex.Sum(x => x.Size);
+
+ // Get the sum of the total size of the single or segmented packages
+ return _assetIndex.Sum(asset =>
{
- LogWriteLine(asset.PathOutput);
- try
+ // Check if the package is segmented
+ if (asset.Segments != null && asset.Segments.Count != 0)
{
- resultSlice= asset.Segments != null && asset.Segments.Count != 0 ?
- asset.Segments.Select(selector: x => x.GetReadStream(_downloadThreadCount)).ToArray().Length>0 : asset.GetReadStream(_downloadThreadCount).Length>0;
+ // Get the sum of the total size/length for each of its streams
+ return asset.Segments.Sum(segment =>
+ {
+ // Check if the read stream exist
+ if (segment.IsReadStreamExist(_downloadThreadCount))
+ {
+ // Get the stream of the segment and using (and auto dispose) it
+ using Stream segmentStream = segment.GetReadStream(_downloadThreadCount);
+ // Return the size/length of the stream
+ return segmentStream.Length;
+ }
+ // If not, then return 0
+ return 0;
+ });
}
- catch (Exception ex)
+
+ // If segment is none, check if the single stream exist
+ if (asset.IsReadStreamExist(_downloadThreadCount))
{
- LogWriteLine(ex.ToString(), LogType.Default);
- continue;
+ // If yes, then using single stream
+ using Stream singleStream = asset.GetReadStream(_downloadThreadCount);
+ // Return the size of the stream
+ return singleStream.Length;
}
- }
- resultZip = _gameVersionManager.GetGamePreloadZip().All(x =>
- {
- string name = Path.GetFileName(x.path);
- string path = Path.Combine(_gamePath, name);
- return File.Exists(path);
- });
- if (resultZip) LogWriteLine("Zip Found");
- if (resultSlice) LogWriteLine("Slices found");
- return resultSlice || resultZip;
+ // If neither of both exist, then return 0
+ return 0;
+ }) == totalPackageSize; // Then compare if the total package size is equal
+ // Note:
+ // x.GetReadStream() will check if the single package/zip exist.
+ // So checking the fully downloaded single package is unnecessary.
}
public async Task MoveGameLocation()
@@ -420,7 +482,7 @@ public async ValueTask UninstallGame()
{
string GameFolder = ConverterTool.NormalizePath(_gamePath);
- switch (await Dialog_UninstallGame(_parentUI, GameFolder, _gamePreset.ZoneFullname))
+ switch (await Dialog_UninstallGame(_parentUI, GameFolder, _gameVersionManager.GamePreset.ZoneFullname))
{
case ContentDialogResult.Primary:
try
@@ -431,7 +493,7 @@ public async ValueTask UninstallGame()
{
LogWriteLine($"Failed while deleting the game folder: {GameFolder}\r\n{ex}", LogType.Error, true);
}
- PageStatics._GameVersion.Reinitialize();
+ _gameVersionManager.Reinitialize();
return true;
default:
return false;
@@ -609,7 +671,7 @@ public virtual List TryGetHDiffList()
.Deserialize(
listReader.ReadLine(),
typeof(PkgVersionProperties),
- PkgVersionPropertiesContext.Default);
+ CoreLibraryJSONContext.Default);
string filePath = Path.Combine(_gamePath, prop.remoteName + ".hdiff");
if (File.Exists(filePath))
@@ -691,13 +753,13 @@ private async ValueTask CheckExistingBHI3LInstallation()
private async ValueTask CheckExistingOfficialInstallation()
{
- if (_gamePreset.CheckExistingGame())
+ if (_gameVersionManager.GamePreset.CheckExistingGame())
{
- switch (await Dialog_ExistingInstallation(_parentUI))
+ switch (await Dialog_ExistingInstallation(_parentUI, _gameVersionManager.GamePreset.ActualGameDataLocation))
{
// If action to migrate was taken, then update the game path (but don't save it to the config file)
case ContentDialogResult.Primary:
- _gameVersionManager.UpdateGamePath(_gamePreset.ActualGameDataLocation.Replace('\\', '/'), false);
+ _gameVersionManager.UpdateGamePath(_gameVersionManager.GamePreset.ActualGameDataLocation.Replace('\\', '/'), false);
return 0;
// If action to fresh install was taken, then return 2 (selecting path)
case ContentDialogResult.Secondary:
@@ -715,9 +777,9 @@ private async ValueTask CheckExistingOfficialInstallation()
private bool TryGetExistingSteamPath(ref string OutputPath)
{
// If the game preset doesn't have SteamGameID, then return false
- if (_gamePreset.SteamGameID == null) return false;
+ if (_gameVersionManager.GamePreset.SteamGameID == null) return false;
// Assign Steam ID
- int steamID = _gamePreset.SteamGameID ?? 0;
+ int steamID = _gameVersionManager.GamePreset.SteamGameID ?? 0;
// Try get the list of Steam Libs and Apps
List steamLibsList = SteamTool.GetSteamLibs();
@@ -743,7 +805,7 @@ private bool TryGetExistingBHI3LPath(ref string OutputPath)
{
#nullable enable
// If the preset doesn't have BetterHi3Launcher registry ver info, then return false
- if (_gamePreset.BetterHi3LauncherVerInfoReg == null) return false;
+ if (_gameVersionManager.GamePreset.BetterHi3LauncherVerInfoReg == null) return false;
// Try open BHI3L registry key
// If the key doesn't exist, then return false
@@ -752,7 +814,7 @@ private bool TryGetExistingBHI3LPath(ref string OutputPath)
// Try get the key value
// If the key also doesn't exist, then return false
- byte[]? keyValue = (byte[]?)Key?.GetValue(_gamePreset.BetterHi3LauncherVerInfoReg);
+ byte[]? keyValue = (byte[]?)Key?.GetValue(_gameVersionManager.GamePreset.BetterHi3LauncherVerInfoReg);
if (keyValue == null) return false;
BHI3LInfo? config;
@@ -761,11 +823,11 @@ private bool TryGetExistingBHI3LPath(ref string OutputPath)
{
// Try parsing the config
value = Encoding.UTF8.GetString(keyValue);
- config = (BHI3LInfo?)JsonSerializer.Deserialize(value, typeof(BHI3LInfo), BHI3LInfoContext.Default);
+ config = (BHI3LInfo?)JsonSerializer.Deserialize(value, typeof(BHI3LInfo), CoreLibraryJSONContext.Default);
}
catch (Exception ex)
{
- LogWriteLine($"Registry Value {_gamePreset.BetterHi3LauncherVerInfoReg}:\r\n{value}\r\n\r\nException:\r\n{ex}", LogType.Error, true);
+ LogWriteLine($"Registry Value {_gameVersionManager.GamePreset.BetterHi3LauncherVerInfoReg}:\r\n{value}\r\n\r\nException:\r\n{ex}", LogType.Error, true);
return false;
}
@@ -773,7 +835,7 @@ private bool TryGetExistingBHI3LPath(ref string OutputPath)
if (config != null && config.game_info.installed
&& !string.IsNullOrEmpty(config.game_info.install_path))
{
- FileInfo execPath = new FileInfo(Path.Combine(config.game_info.install_path, _gamePreset.GameExecutableName));
+ FileInfo execPath = new FileInfo(Path.Combine(config.game_info.install_path, _gameVersionManager.GamePreset.GameExecutableName));
OutputPath = config.game_info.install_path;
return execPath.Exists && execPath.Length > 1 >> 16;
}
@@ -797,7 +859,7 @@ private async Task AskGameFolderDialog()
{
// If primary button is clicked, then set folder with the default path
case ContentDialogResult.Primary:
- folder = Path.Combine(LauncherConfig.AppGameFolder, _gamePreset.ProfileName, _gamePreset.GameDirectoryName);
+ folder = Path.Combine(LauncherConfig.AppGameFolder, _gameVersionManager.GamePreset.ProfileName, _gameVersionManager.GamePreset.GameDirectoryName);
isChoosen = true;
break;
// If secondary, then show folder picker dialog to choose the folder
@@ -965,6 +1027,12 @@ private async ValueTask RunPackageDownloadRoutine(GameInstallPackage package, Ca
_status.ActivityStatus = string.Format("{0}: {1}", Lang._Misc.Downloading, string.Format(Lang._Misc.PerFromTo, _progressTotalCountCurrent, _progressTotalCount));
LogWriteLine($"Downloading package URL {_progressTotalCountCurrent}/{_progressTotalCount} ({ConverterTool.SummarizeSizeSimple(package.Size)}): {package.URL}");
+ // Get the directory path
+ string pathDir = Path.GetDirectoryName(package.PathOutput);
+
+ // If the directory doesn't exist, then create one
+ if (!Directory.Exists(pathDir)) Directory.CreateDirectory(pathDir);
+
// If the file exist or package size is unmatched,
// then start downloading
FileInfo packageOutInfo = new FileInfo(package.PathOutput);
@@ -975,7 +1043,10 @@ private async ValueTask RunPackageDownloadRoutine(GameInstallPackage package, Ca
_status.ActivityStatus = string.Format("{0}: {1}", Lang._Misc.Merging, string.Format(Lang._Misc.PerFromTo, _progressTotalCountCurrent, _progressTotalCount));
UpdateStatus();
_stopwatch.Stop();
- // await _httpClient.Merge();
+ if (_canMergeDownloadChunks)
+ {
+ await _httpClient.Merge();
+ }
_stopwatch.Start();
}
@@ -1096,6 +1167,12 @@ private async ValueTask CheckDriveFreeSpace(UIElement Content, List packageList, C
}
#endregion
#region Virtual Methods - StartPackageDownload
+
+ private enum CompletenessStatus { Running, Completed, Cancelled, Idle }
+ private void UpdateCompletenessStatus(CompletenessStatus status)
+ {
+ switch (status)
+ {
+ case CompletenessStatus.Running:
+ IsRunning = true;
+ _status.IsRunning = true;
+ _status.IsCompleted = false;
+ _status.IsCanceled = false;
+ break;
+ case CompletenessStatus.Completed:
+ IsRunning = false;
+ _status.IsRunning = false;
+ _status.IsCompleted = true;
+ _status.IsCanceled = false;
+ break;
+ case CompletenessStatus.Cancelled:
+ IsRunning = false;
+ _status.IsRunning = false;
+ _status.IsCompleted = false;
+ _status.IsCanceled = true;
+ break;
+ case CompletenessStatus.Idle:
+ IsRunning = false;
+ _status.IsRunning = false;
+ _status.IsCompleted = false;
+ _status.IsCanceled = false;
+ break;
+ }
+ UpdateStatus();
+ }
+
protected async Task TryGetPackageRemoteSize(GameInstallPackage asset, CancellationToken token)
{
asset.Size = await _httpClient.TryGetContentLengthAsync(asset.URL, token) ?? 0;
@@ -1190,7 +1301,7 @@ private async void ZipProgressAdapter(object sender, ExtractProgress e)
// Calculate the timelapse
_progress.ProgressTotalTimeLeft = TimeSpan.FromSeconds((_progressTotalSize - _progressTotalSizeCurrent) / ConverterTool.Unzeroed(_progress.ProgressTotalSpeed));
- UpdateProgress();
+ UpdateAll();
}
}
diff --git a/CollapseLauncher/Classes/InstallManagement/GameConversionManagement.cs b/CollapseLauncher/Classes/InstallManagement/GameConversionManagement.cs
index 4e05aa44c..ba097071b 100644
--- a/CollapseLauncher/Classes/InstallManagement/GameConversionManagement.cs
+++ b/CollapseLauncher/Classes/InstallManagement/GameConversionManagement.cs
@@ -3,6 +3,7 @@
using Hi3Helper.Http;
using Hi3Helper.Preset;
using Hi3Helper.Shared.ClassStruct;
+using Hi3Helper.SharpHDiffPatch;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -73,7 +74,7 @@ public async Task StartPreparation()
ConvertDetail = Lang._InstallConvert.Step2Subtitle;
await FallbackCDNUtil.DownloadCDNFallbackContent(_http, buffer, URL, Token);
buffer.Position = 0;
- SourceFileRemote = (List)JsonSerializer.Deserialize(buffer, typeof(List), L_FilePropertiesRemoteContext.Default);
+ SourceFileRemote = (List)JsonSerializer.Deserialize(buffer, typeof(List), CoreLibraryJSONContext.Default);
}
using (MemoryStream buffer = new MemoryStream())
@@ -82,7 +83,7 @@ public async Task StartPreparation()
ConvertDetail = Lang._InstallConvert.Step2Subtitle;
await FallbackCDNUtil.DownloadCDNFallbackContent(_http, buffer, URL, Token);
buffer.Position = 0;
- TargetFileRemote = (List)JsonSerializer.Deserialize(buffer, typeof(List), L_FilePropertiesRemoteContext.Default);
+ TargetFileRemote = (List)JsonSerializer.Deserialize(buffer, typeof(List), CoreLibraryJSONContext.Default);
}
}
finally
@@ -159,13 +160,16 @@ private async Task> VerifyIngredients(List
{
await Task.Run(() =>
{
- LocalHash = Entry.DataType != FileType.Blocks ?
- BytesToCRC32Simple(fs) :
- CreateMD5Shared(fs);
+ LocalHash = Entry.CurrCRC.Length > 8 ?
+ CreateMD5Shared(fs) :
+ BytesToCRC32Simple(fs);
Token.ThrowIfCancellationRequested();
if (LocalHash.ToLower() != Entry.CurrCRC)
+ {
+ LogWriteLine($"File {Entry.FileName} has unmatched hash. Local: {LocalHash.ToLower()} Remote: {Entry.CurrCRC}", LogType.Warning, true);
BrokenManifest.Add(Entry);
+ }
}, Token);
}
}
@@ -278,10 +282,6 @@ private void FetchIngredientsAPI_Progress(object sender, DownloadEvent e)
ConvertStatus, ConvertDetail);
}
- FileSystemWatcher ConvertFsWatcher;
-
- long ConvertRead = 0;
- long ConvertTotalSize = 0;
public async Task StartConversion()
{
ResetSw();
@@ -294,26 +294,20 @@ public async Task StartConversion()
TryDirectoryDelete(OutputPath, true);
Directory.CreateDirectory(OutputPath);
- ConvertTotalSize = TargetFileManifest.Sum(x => x.FileSize);
- ConvertFsWatcher = new FileSystemWatcher()
- {
- Path = OutputPath,
- NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName
- | NotifyFilters.Size,
- IncludeSubdirectories = true,
- EnableRaisingEvents = true
- };
+ EventListener.PatchEvent += EventListener_PatchEvent;
- ConvertFsWatcher.Created += ConvertFsWatcher_Created;
+ await Task.Run(() =>
+ {
+ HDiffPatch patch = new HDiffPatch();
+ patch.Initialize(CookbookPath);
+ patch.Patch(IngredientsPath, OutputPath, false, Token);
+ }, Token);
- await Task.Run(() => new HPatchUtil().HPatchDir(IngredientsPath, CookbookPath, OutputPath), Token);
TryDirectoryDelete(IngredientsPath, true);
TryFileDelete(CookbookPath);
MoveMiscSourceFiles(SourceProfile.ActualGameDataLocation, OutputPath);
TryDirectoryDelete(SourceProfile.ActualGameDataLocation, true);
-
- ConvertFsWatcher.Created -= ConvertFsWatcher_Created;
}
catch (Exception ex)
{
@@ -329,6 +323,16 @@ public async Task StartConversion()
LogWriteLine($"Conversion process has failed! But don't worry, the files have been reverted :D\r\n{ex}", LogType.Error, true);
throw new Exception($"Conversion process has failed! But don't worry, the file have been reverted :D\r\n{ex}", ex);
}
+ finally
+ {
+ EventListener.PatchEvent -= EventListener_PatchEvent;
+ }
+ }
+
+ private void EventListener_PatchEvent(object sender, PatchEvent e)
+ {
+ ConvertDetail = string.Format(Lang._Misc.Converting, "");
+ UpdateProgress(e.CurrentSizePatched, e.TotalSizeToBePatched, 1, 1, e.TimeLeft, ConvertStatus, ConvertDetail);
}
private void TryFileDelete(string Input)
@@ -390,19 +394,6 @@ private void MoveMiscSourceFiles(string InputPath, string OutputPath)
}
}
- string lastName = null;
- private void ConvertFsWatcher_Created(object sender, FileSystemEventArgs e)
- {
- if (!Directory.Exists(e.FullPath))
- {
- ConvertDetail = string.Format(Lang._Misc.Converting, e.Name);
- UpdateProgress(ConvertRead, ConvertTotalSize, 1, 1, ConvertSw.Elapsed, ConvertStatus, ConvertDetail);
- if (lastName != null)
- ConvertRead += new FileInfo(lastName).Length;
- lastName = e.FullPath;
- }
- }
-
public void UpdateProgress(long StartSize, long EndSize, int StartCount, int EndCount,
TimeSpan TimeSpan, string StatusMsg = "", string DetailMsg = "", bool UseCountUnit = false)
{
diff --git a/CollapseLauncher/Classes/InstallManagement/Genshin/GenshinInstall.cs b/CollapseLauncher/Classes/InstallManagement/Genshin/GenshinInstall.cs
index d12c2ec19..011f6618b 100644
--- a/CollapseLauncher/Classes/InstallManagement/Genshin/GenshinInstall.cs
+++ b/CollapseLauncher/Classes/InstallManagement/Genshin/GenshinInstall.cs
@@ -18,11 +18,11 @@ namespace CollapseLauncher.InstallManager.Genshin
internal class GenshinInstall : InstallManagerBase, IGameInstallManager
{
#region Override Properties
- protected override int _gameVoiceLanguageID { get => _gamePreset.GetVoiceLanguageID(); }
+ protected override int _gameVoiceLanguageID { get => _gameVersionManager.GamePreset.GetVoiceLanguageID(); }
#endregion
#region Private Properties
- private string _gameDataPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName)}_Data"); }
+ private string _gameDataPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gameVersionManager.GamePreset.GameExecutableName)}_Data"); }
private string _gameDataPersistentPath { get => Path.Combine(_gameDataPath, "Persistent"); }
private string _gameAudioLangListPath
{
@@ -48,20 +48,20 @@ private string _gameAudioLangListPath
private string _gameAudioOldPath { get => Path.Combine(_gameDataPath, "StreamingAssets", "Audio", "GeneratedSoundBanks", "Windows"); }
#endregion
- public GenshinInstall(UIElement parentUI)
- : base(parentUI)
+ public GenshinInstall(UIElement parentUI, IGameVersionCheck GameVersionManager)
+ : base(parentUI, GameVersionManager)
{
}
#region Public Methods
- public override async Task StartPackageInstallation()
+ protected override async Task StartPackageInstallationInner()
{
// Starting from 3.6 update, the Audio files have been moved to "AudioAssets" folder
EnsureMoveOldToNewAudioDirectory();
// Run the base installation process
- await base.StartPackageInstallation();
+ await base.StartPackageInstallationInner();
// Then start on processing hdifffiles list and deletefiles list
await ApplyHdiffListPatch();
@@ -105,7 +105,7 @@ private void EnsureMoveOldToNewAudioDirectory()
}
}
- public override bool IsPreloadCompleted()
+ public override async ValueTask IsPreloadCompleted()
{
// Get the primary file first check
List resource = _gameVersionManager.GetGamePreloadZip();
@@ -198,7 +198,7 @@ protected override async ValueTask TryAddResourceVersionList(RegionResourceVersi
packageList.Add(package);
// Set the voice language ID to value given
- _gamePreset.SetVoiceLanguageID(langID);
+ _gameVersionManager.GamePreset.SetVoiceLanguageID(langID);
LogWriteLine($"Adding primary {package.LanguageName} audio package: {package.Name} to the list (Hash: {package.HashString})", LogType.Default, true);
}
diff --git a/CollapseLauncher/Classes/InstallManagement/Honkai/HonkaiInstall.cs b/CollapseLauncher/Classes/InstallManagement/Honkai/HonkaiInstall.cs
index ea7ca4581..26944046e 100644
--- a/CollapseLauncher/Classes/InstallManagement/Honkai/HonkaiInstall.cs
+++ b/CollapseLauncher/Classes/InstallManagement/Honkai/HonkaiInstall.cs
@@ -2,10 +2,9 @@
using CollapseLauncher.InstallManager.Base;
using CollapseLauncher.Interfaces;
using CollapseLauncher.Pages;
-using CollapseLauncher.Statics;
using Hi3Helper;
-using Hi3Helper.Data;
using Hi3Helper.Shared.ClassStruct;
+using Hi3Helper.SharpHDiffPatch;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
@@ -27,19 +26,21 @@ internal class HonkaiInstall : InstallManagerBase, IGameI
#endregion
#region Private Properties
+ private HonkaiCache _gameCacheManager { get; set; }
private bool _forceIgnoreDeltaPatch = false;
- private FileSystemWatcher _deltaPatchWatcher;
#endregion
- public HonkaiInstall(UIElement parentUI)
- : base(parentUI)
+ public HonkaiInstall(UIElement parentUI, IGameVersionCheck GameVersionManager, ICache GameCacheManager, IGameSettings GameSettings)
+ : base(parentUI, GameVersionManager)
{
-
+ _gameSettings = GameSettings;
+ _gameCacheManager = GameCacheManager as HonkaiCache;
}
#region Public Methods
public override async ValueTask StartPackageVerification()
{
+ IsRunning = true;
DeltaPatchProperty patchProperty = _gameDeltaPatchProperty;
// Check if the game has delta patch and in NeedsUpdate status. If true, then
@@ -58,8 +59,11 @@ public override async ValueTask StartPackageVerification()
return -1;
}
+ // Always reset the token
+ ResetToken();
+
// Initialize repair tool
- _gameRepairTool = new HonkaiRepair(_parentUI, true, patchProperty.SourceVer);
+ _gameRepairTool = new HonkaiRepair(_parentUI, _gameVersionManager, _gameCacheManager, _gameSettings, true, patchProperty.SourceVer);
try
{
// Set the activity
@@ -83,7 +87,11 @@ public override async ValueTask StartPackageVerification()
await _gameRepairTool.StartRepairRoutine(true);
}
}
- catch { throw; }
+ catch
+ {
+ IsRunning = false;
+ throw;
+ }
finally
{
// Unsubscribe the progress event
@@ -98,7 +106,7 @@ public override async ValueTask StartPackageVerification()
return await base.StartPackageVerification();
}
- public override async Task StartPackageInstallation()
+ protected override async Task StartPackageInstallationInner()
{
if (_canDeltaPatch && _gameInstallationStatus == GameInstallStateEnum.NeedsUpdate && !_forceIgnoreDeltaPatch)
{
@@ -107,19 +115,9 @@ public override async Task StartPackageInstallation()
string previousPath = _gamePath;
string ingredientPath = previousPath.TrimEnd('\\') + "_Ingredients";
- // Initialize the filesystem watcher to check file changes on event
- _deltaPatchWatcher = new FileSystemWatcher()
- {
- Path = previousPath,
- NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName
- | NotifyFilters.Size,
- IncludeSubdirectories = true,
- EnableRaisingEvents = true
- };
-
try
{
- List localAssetIndex = (_gameRepairTool as HonkaiRepair).GetAssetIndex();
+ List localAssetIndex = ((HonkaiRepair)_gameRepairTool).GetAssetIndex();
MoveFileToIngredientList(localAssetIndex, previousPath, ingredientPath);
// Get the sum of uncompressed size and
@@ -128,13 +126,19 @@ public override async Task StartPackageInstallation()
_progressTotalSizeCurrent = 0;
_progressTotalCountCurrent = 1;
_status.IsIncludePerFileIndicator = false;
+ _status.IsProgressTotalIndetermined = true;
_status.ActivityStatus = Lang._Misc.ApplyingPatch;
UpdateStatus();
RestartStopwatch();
// Start the patching process
- _deltaPatchWatcher.Created += DeltaPatchWatcherProgress;
- await Task.Run(() => new HPatchUtil().HPatchDir(ingredientPath, patchProperty.PatchPath, previousPath));
+ EventListener.PatchEvent += DeltaPatchCheckProgress;
+ await Task.Run(() =>
+ {
+ HDiffPatch patch = new HDiffPatch();
+ patch.Initialize(patchProperty.PatchPath);
+ patch.Patch(ingredientPath, previousPath, false, _token.Token);
+ });
// Remove ingredient folder
Directory.Delete(ingredientPath, true);
@@ -154,13 +158,12 @@ public override async Task StartPackageInstallation()
}
finally
{
- _deltaPatchWatcher.Created -= DeltaPatchWatcherProgress;
- _deltaPatchWatcher?.Dispose();
+ EventListener.PatchEvent -= DeltaPatchCheckProgress;
}
}
// If no delta patch is happening, then do the base installation
- await base.StartPackageInstallation();
+ await base.StartPackageInstallationInner();
}
public override async ValueTask TryShowFailedDeltaPatchState()
@@ -171,7 +174,7 @@ public override async ValueTask TryShowFailedDeltaPatchState()
// If path doesn't exist, then return false
if (!Directory.Exists(GamePathIngredients)) return false;
- LogWriteLine($"Previous failed delta patch has been detected on Game {_gamePreset.ZoneFullname} ({GamePathIngredients})", LogType.Warning, true);
+ LogWriteLine($"Previous failed delta patch has been detected on Game {_gameVersionManager.GamePreset.ZoneFullname} ({GamePathIngredients})", LogType.Warning, true);
// Show action dialog
switch (await Dialog_PreviousDeltaPatchInstallFailed(_parentUI))
{
@@ -199,7 +202,7 @@ public override async ValueTask TryShowFailedGameConversionState()
long FileSize = Directory.EnumerateFiles(GamePathIngredients).Sum(x => new FileInfo(x).Length);
if (FileSize < 1 << 20) return false;
- LogWriteLine($"Previous failed game conversion has been detected on Game: {_gamePreset.ZoneFullname} ({GamePathIngredients})", LogType.Warning, true);
+ LogWriteLine($"Previous failed game conversion has been detected on Game: {_gameVersionManager.GamePreset.ZoneFullname} ({GamePathIngredients})", LogType.Warning, true);
// Show action dialog
switch (await Dialog_PreviousGameConversionFailed(_parentUI))
{
@@ -281,15 +284,15 @@ private void MoveFileToIngredientList(List assetIndex, str
#endregion
#region Event Methods
- private async void DeltaPatchCheckProgress(object sender, TotalPerfileProgress e)
+ private async void DeltaPatchCheckProgress(object sender, PatchEvent e)
{
- _progress.ProgressTotalPercentage = e.ProgressTotalPercentage == 0 ? e.ProgressPerFilePercentage : e.ProgressTotalPercentage;
+ _progress.ProgressTotalPercentage = e.ProgressPercentage;
- _progress.ProgressTotalTimeLeft = e.ProgressTotalTimeLeft;
- _progress.ProgressTotalSpeed = e.ProgressTotalSpeed;
+ _progress.ProgressTotalTimeLeft = e.TimeLeft;
+ _progress.ProgressTotalSpeed = e.Speed;
- _progress.ProgressTotalSizeToDownload = e.ProgressTotalSizeToDownload;
- _progress.ProgressTotalDownload = e.ProgressTotalDownload;
+ _progress.ProgressTotalSizeToDownload = e.TotalSizeToBePatched;
+ _progress.ProgressTotalDownload = e.CurrentSizePatched;
if (await CheckIfNeedRefreshStopwatch())
{
@@ -299,29 +302,21 @@ private async void DeltaPatchCheckProgress(object sender, TotalPerfileProgress e
}
}
- string lastName = null;
- private void DeltaPatchWatcherProgress(object sender, FileSystemEventArgs e)
+ private async void DeltaPatchCheckProgress(object sender, TotalPerfileProgress e)
{
- if (!Directory.Exists(e.FullPath))
- {
- if (lastName != null)
- _progressTotalSizeCurrent += new FileInfo(lastName).Length;
- lastName = e.FullPath;
-
- // Assign local sizes to progress
- _progress.ProgressTotalDownload = _progressTotalSizeCurrent;
- _progress.ProgressTotalSizeToDownload = _progressTotalSize;
-
- // Calculate the speed
- _progress.ProgressTotalSpeed = _progressTotalSizeCurrent / _stopwatch.Elapsed.TotalSeconds;
+ _progress.ProgressTotalPercentage = e.ProgressTotalPercentage == 0 ? e.ProgressPerFilePercentage : e.ProgressTotalPercentage;
- // Calculate percentage
- _progress.ProgressTotalPercentage = Math.Round(((double)_progressTotalSizeCurrent / _progressTotalSize) * 100, 2);
+ _progress.ProgressTotalTimeLeft = e.ProgressTotalTimeLeft;
+ _progress.ProgressTotalSpeed = e.ProgressTotalSpeed;
- // Calculate the timelapse
- _progress.ProgressTotalTimeLeft = TimeSpan.FromSeconds((_progressTotalSize - _progressTotalSizeCurrent) / ConverterTool.Unzeroed(_progress.ProgressTotalSpeed));
+ _progress.ProgressTotalSizeToDownload = e.ProgressTotalSizeToDownload;
+ _progress.ProgressTotalDownload = e.ProgressTotalDownload;
- UpdateProgress();
+ if (await CheckIfNeedRefreshStopwatch())
+ {
+ _status.IsProgressTotalIndetermined = false;
+ UpdateProgressBase();
+ UpdateStatus();
}
}
#endregion
@@ -334,7 +329,7 @@ private string GetFailedGameConversionFolder(string basepath)
// Step back once from the game directory
string ParentPath = Path.GetDirectoryName(basepath);
// Get the ingredient path
- string IngredientPath = Directory.EnumerateDirectories(ParentPath, $"{PageStatics._GameVersion.GamePreset.GameDirectoryName}*_ConvertedTo-*_Ingredients", SearchOption.TopDirectoryOnly)
+ string IngredientPath = Directory.EnumerateDirectories(ParentPath, $"{_gameVersionManager.GamePreset.GameDirectoryName}*_ConvertedTo-*_Ingredients", SearchOption.TopDirectoryOnly)
.FirstOrDefault();
// If the path is not null, then return
if (IngredientPath is not null) return IngredientPath;
diff --git a/CollapseLauncher/Classes/InstallManagement/StarRail/StarRailInstall.cs b/CollapseLauncher/Classes/InstallManagement/StarRail/StarRailInstall.cs
index b4d423c47..f118c8e45 100644
--- a/CollapseLauncher/Classes/InstallManagement/StarRail/StarRailInstall.cs
+++ b/CollapseLauncher/Classes/InstallManagement/StarRail/StarRailInstall.cs
@@ -15,20 +15,20 @@ namespace CollapseLauncher.InstallManager.StarRail
internal class StarRailInstall : InstallManagerBase, IGameInstallManager
{
#region Override Properties
- protected override int _gameVoiceLanguageID { get => _gamePreset.GetVoiceLanguageID(); }
+ protected override int _gameVoiceLanguageID { get => _gameVersionManager.GamePreset.GetVoiceLanguageID(); }
#endregion
- public StarRailInstall(UIElement parentUI)
- : base(parentUI)
+ public StarRailInstall(UIElement parentUI, IGameVersionCheck GameVersionManager)
+ : base(parentUI, GameVersionManager)
{
}
#region Public Methods
- public override async Task StartPackageInstallation()
+ protected override async Task StartPackageInstallationInner()
{
// Run the base installation process
- await base.StartPackageInstallation();
+ await base.StartPackageInstallationInner();
// Then start on processing hdifffiles list and deletefiles list
await ApplyHdiffListPatch();
@@ -55,10 +55,10 @@ protected override async ValueTask TryAddResourceVersionList(RegionResourceVersi
langID = await Dialog_ChooseAudioLanguage(_parentUI, langStrings);
// Set the voice language ID to value given
- _gamePreset.SetVoiceLanguageID(langID);
+ _gameVersionManager.GamePreset.SetVoiceLanguageID(langID);
}
- LogWriteLine($"Setting audio ID to: {_gamePreset.GetStarRailVoiceLanguageFullNameByID(_gameVoiceLanguageID)}", LogType.Default, true);
+ LogWriteLine($"Setting audio ID to: {_gameVersionManager.GamePreset.GetStarRailVoiceLanguageFullNameByID(_gameVoiceLanguageID)}", LogType.Default, true);
}
private List EnumerateAudioLanguageString()
diff --git a/CollapseLauncher/Classes/Interfaces/Class/CommunityToolsProperty.cs b/CollapseLauncher/Classes/Interfaces/Class/CommunityToolsProperty.cs
index fd3036262..6ecd1eadd 100644
--- a/CollapseLauncher/Classes/Interfaces/Class/CommunityToolsProperty.cs
+++ b/CollapseLauncher/Classes/Interfaces/Class/CommunityToolsProperty.cs
@@ -40,7 +40,7 @@ public static CommunityToolsProperty LoadCommunityTools()
{
if (!File.Exists(filePath)) throw new FileNotFoundException("Community Tools file is not found!", filePath);
- return (CommunityToolsProperty)JsonSerializer.Deserialize(File.ReadAllText(filePath), typeof(CommunityToolsProperty), CommunityToolsPropertyContext.Default);
+ return (CommunityToolsProperty)JsonSerializer.Deserialize(File.ReadAllText(filePath), typeof(CommunityToolsProperty), InternalAppJSONContext.Default);
}
catch (Exception ex)
{
diff --git a/CollapseLauncher/Classes/Interfaces/Class/GamePropertyBase.cs b/CollapseLauncher/Classes/Interfaces/Class/GamePropertyBase.cs
index 69c51524b..01955b23a 100644
--- a/CollapseLauncher/Classes/Interfaces/Class/GamePropertyBase.cs
+++ b/CollapseLauncher/Classes/Interfaces/Class/GamePropertyBase.cs
@@ -1,6 +1,4 @@
-using CollapseLauncher.Statics;
-using Hi3Helper.Preset;
-using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@@ -16,8 +14,15 @@ internal class GamePropertyBase : IAssetEntry where T1 : Enum
private GameVersion _gameVersionOverride { get; init; }
private bool _isVersionOverride { get; init; }
- public GamePropertyBase(UIElement parentUI, string gamePath, string gameRepoURL, string versionOverride)
+ public GamePropertyBase(UIElement parentUI, IGameVersionCheck gameVersionManager, IGameSettings gameSettings, string gamePath, string gameRepoURL, string versionOverride)
+ : this(parentUI, gameVersionManager, gamePath, gameRepoURL, versionOverride)
{
+ _gameSettings = gameSettings;
+ }
+
+ public GamePropertyBase(UIElement parentUI, IGameVersionCheck gameVersionManager, string gamePath, string gameRepoURL, string versionOverride)
+ {
+ _gameVersionManager = gameVersionManager;
_parentUI = parentUI;
_gamePathField = gamePath;
_gameRepoURL = gameRepoURL;
@@ -39,16 +44,17 @@ public GamePropertyBase(UIElement parentUI, string gamePath, string gameRepoURL,
protected byte _downloadThreadCount { get => (byte)AppCurrentDownloadThread; }
protected byte _threadCount { get => (byte)AppCurrentThread; }
protected CancellationTokenSource _token { get; set; }
- protected UIElement _parentUI { get; init; }
protected Stopwatch _stopwatch { get; set; }
protected Stopwatch _refreshStopwatch { get; set; }
- protected string _gamePath { get => string.IsNullOrEmpty(_gamePathField) ? PageStatics._GameVersion.GameDirPath : _gamePathField; }
+ protected GameVersion _gameVersion { get => _isVersionOverride ? _gameVersionOverride : _gameVersionManager.GetGameExistingVersion().Value; }
+ protected IGameVersionCheck _gameVersionManager { get; set; }
+ protected IGameSettings _gameSettings { get; set; }
+ protected string _gamePath { get => string.IsNullOrEmpty(_gamePathField) ? _gameVersionManager.GameDirPath : _gamePathField; }
protected string _gameRepoURL { get; set; }
- protected PresetConfigV2 _gamePreset { get => PageStatics._GameVersion.GamePreset; }
- protected GameVersion _gameVersion { get => _isVersionOverride ? _gameVersionOverride : PageStatics._GameVersion.GetGameExistingVersion().Value; }
protected List _assetIndex { get; set; }
protected bool _useFastMethod { get; set; }
public ObservableCollection> AssetEntry { get; set; }
+ public UIElement _parentUI { get; init; }
}
}
diff --git a/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs b/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs
index 53fe2cbea..b391cb936 100644
--- a/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs
+++ b/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs
@@ -22,8 +22,13 @@ internal class ProgressBase :
GamePropertyBase where T1 : Enum
where T2 : IAssetIndexSummary
{
- public ProgressBase(UIElement parentUI, string gamePath, string gameRepoURL, string versionOverride)
- : base(parentUI, gamePath, gameRepoURL, versionOverride)
+ public ProgressBase(UIElement parentUI, IGameVersionCheck GameVersionManager, IGameSettings GameSettings, string gamePath, string gameRepoURL, string versionOverride)
+ : base(parentUI, GameVersionManager, GameSettings, gamePath, gameRepoURL, versionOverride) => Init();
+
+ public ProgressBase(UIElement parentUI, IGameVersionCheck GameVersionManager, string gamePath, string gameRepoURL, string versionOverride)
+ : base(parentUI, GameVersionManager, gamePath, gameRepoURL, versionOverride) => Init();
+
+ private void Init()
{
_status = new TotalPerfileStatus() { IsIncludePerFileIndicator = true };
_progress = new TotalPerfileProgress();
@@ -526,6 +531,8 @@ protected async Task SpawnRepairDialog(List assetIndex, Action actionIfInter
#endregion
#region HandlerUpdaters
+ public void Dispatch(DispatcherQueueHandler handler) => _parentUI.DispatcherQueue.TryEnqueue(handler);
+
protected virtual void PopRepairAssetEntry() => Dispatch(() =>
{
try
@@ -582,7 +589,6 @@ protected virtual void UpdateRepairStatus(string activityStatus, string activity
UpdateStatus();
}
- protected void Dispatch(DispatcherQueueHandler handler) => _parentUI.DispatcherQueue.TryEnqueue(handler);
protected async Task CheckIfNeedRefreshStopwatch()
{
if (_refreshStopwatch.ElapsedMilliseconds > _refreshInterval)
diff --git a/CollapseLauncher/Classes/Interfaces/IBackgroundActivity.cs b/CollapseLauncher/Classes/Interfaces/IBackgroundActivity.cs
new file mode 100644
index 000000000..b77aae1c4
--- /dev/null
+++ b/CollapseLauncher/Classes/Interfaces/IBackgroundActivity.cs
@@ -0,0 +1,16 @@
+using Microsoft.UI.Dispatching;
+using Microsoft.UI.Xaml;
+using System;
+
+namespace CollapseLauncher.Interfaces
+{
+ internal interface IBackgroundActivity
+ {
+ event EventHandler ProgressChanged;
+ event EventHandler StatusChanged;
+ bool IsRunning { get; }
+ UIElement _parentUI { get; }
+ void CancelRoutine();
+ void Dispatch(DispatcherQueueHandler handler);
+ }
+}
diff --git a/CollapseLauncher/Classes/Interfaces/IGameInstallManager.cs b/CollapseLauncher/Classes/Interfaces/IGameInstallManager.cs
index 9cc322193..c85624c88 100644
--- a/CollapseLauncher/Classes/Interfaces/IGameInstallManager.cs
+++ b/CollapseLauncher/Classes/Interfaces/IGameInstallManager.cs
@@ -1,13 +1,9 @@
-using System;
-using System.Threading.Tasks;
+using System.Threading.Tasks;
namespace CollapseLauncher.Interfaces
{
- internal interface IGameInstallManager
+ internal interface IGameInstallManager : IBackgroundActivity
{
- event EventHandler ProgressChanged;
- event EventHandler StatusChanged;
-
ValueTask GetInstallationPath();
Task StartPackageDownload(bool skipDialog = false);
ValueTask StartPackageVerification();
@@ -18,8 +14,7 @@ internal interface IGameInstallManager
Task MoveGameLocation();
ValueTask UninstallGame();
void Flush();
- void CancelRoutine();
- bool IsPreloadCompleted();
+ ValueTask IsPreloadCompleted();
ValueTask TryShowFailedDeltaPatchState();
ValueTask TryShowFailedGameConversionState();
diff --git a/CollapseLauncher/Classes/PageStatics.cs b/CollapseLauncher/Classes/PageStatics.cs
index 2597294f6..4bf8a75bf 100644
--- a/CollapseLauncher/Classes/PageStatics.cs
+++ b/CollapseLauncher/Classes/PageStatics.cs
@@ -1,14 +1,207 @@
-using CollapseLauncher.Interfaces;
+using CollapseLauncher.GameSettings.Genshin;
+using CollapseLauncher.GameSettings.Honkai;
+using CollapseLauncher.GameSettings.StarRail;
+using CollapseLauncher.GameVersioning;
+using CollapseLauncher.InstallManager.Genshin;
+using CollapseLauncher.InstallManager.Honkai;
+using CollapseLauncher.InstallManager.StarRail;
+using CollapseLauncher.Interfaces;
+using Hi3Helper;
+using Hi3Helper.Preset;
+using Hi3Helper.Shared.ClassStruct;
+using Microsoft.UI.Xaml;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace CollapseLauncher.Statics
{
+ internal class GamePresetProperty
+ {
+ internal GamePresetProperty(UIElement UIElementParent, RegionResourceProp APIResouceProp, PresetConfigV2 GamePreset)
+ {
+ _GamePreset = CopyGamePreset(GamePreset);
+ _APIResouceProp = APIResouceProp.Copy();
+
+ switch (GamePreset.GameType)
+ {
+ case GameType.Honkai:
+ _GameVersion = new GameTypeHonkaiVersion(UIElementParent, _APIResouceProp, _GamePreset);
+ _GameSettings = new HonkaiSettings(_GameVersion);
+ _GameCache = new HonkaiCache(UIElementParent, _GameVersion);
+ _GameRepair = new HonkaiRepair(UIElementParent, _GameVersion, _GameCache, _GameSettings);
+ _GameInstall = new HonkaiInstall(UIElementParent, _GameVersion, _GameCache, _GameSettings);
+ break;
+ case GameType.StarRail:
+ _GameVersion = new GameTypeStarRailVersion(UIElementParent, _APIResouceProp, _GamePreset);
+ _GameSettings = new StarRailSettings(_GameVersion);
+ _GameCache = new StarRailCache(UIElementParent, _GameVersion);
+ _GameRepair = new StarRailRepair(UIElementParent, _GameVersion);
+ _GameInstall = new StarRailInstall(UIElementParent, _GameVersion);
+ break;
+ case GameType.Genshin:
+ _GameVersion = new GameTypeGenshinVersion(UIElementParent, _APIResouceProp, _GamePreset);
+ _GameSettings = new GenshinSettings(_GameVersion);
+ _GameCache = null;
+ _GameRepair = new GenshinRepair(UIElementParent, _GameVersion, _GameVersion.GameAPIProp.data.game.latest.decompressed_path);
+ _GameInstall = new GenshinInstall(UIElementParent, _GameVersion);
+ break;
+ default:
+ throw new NotSupportedException($"[GamePresetProperty.Ctor] Game type: {GamePreset.GameType} ({GamePreset.ProfileName} - {GamePreset.ZoneName}) is not supported!");
+ }
+ }
+
+ private static T[] CopyReturn(T[] Source)
+ {
+ if (Source == null) return null;
+ T[] returnNew = new T[Source.Length];
+ Array.Copy(Source, returnNew, Source.Length);
+ return returnNew;
+ }
+
+ private static List CopyReturn(IEnumerable Source)
+ {
+ if (Source == null) return null;
+ return new List(Source);
+ }
+
+ #region Goofy Ah Copy Method. TODO: Use Generics for this :pepehands:
+ private PresetConfigV2 CopyGamePreset(PresetConfigV2 GamePreset) => new PresetConfigV2()
+ {
+ ActualGameDataLocation = GamePreset.ActualGameDataLocation,
+ BetterHi3LauncherVerInfoReg = GamePreset.BetterHi3LauncherVerInfoReg,
+ ConvertibleTo = CopyReturn(GamePreset.ConvertibleTo),
+ DispatcherKey = GamePreset.DispatcherKey,
+ DispatcherKeyBitLength = GamePreset.DispatcherKeyBitLength,
+ FallbackGameType = GamePreset.FallbackGameType,
+ FallbackLanguage = GamePreset.FallbackLanguage,
+ GameChannel = GamePreset.GameChannel,
+ GameDefaultCVLanguage = GamePreset.GameDefaultCVLanguage,
+ GameDirectoryName = GamePreset.GameDirectoryName,
+ GameDispatchArrayURL = CopyReturn(GamePreset.GameDispatchArrayURL),
+ GameDispatchChannelName = GamePreset.GameDispatchChannelName,
+ GameDispatchDefaultName = GamePreset.GameDispatchDefaultName,
+ GameDispatchURL = GamePreset.GameDispatchURL,
+ GameDispatchURLTemplate = GamePreset.GameDispatchURLTemplate,
+ GameExecutableName = GamePreset.GameExecutableName,
+ GameGatewayDefault = GamePreset.GameGatewayDefault,
+ GameGatewayURLTemplate = GamePreset.GameGatewayURLTemplate,
+ GameName = GamePreset.GameName,
+ GameSupportedLanguages = CopyReturn(GamePreset.GameSupportedLanguages),
+ GameType = GamePreset.GameType,
+ HashID = GamePreset.HashID,
+ InternalGameNameFolder = GamePreset.InternalGameNameFolder,
+ InternalGameNameInConfig = GamePreset.InternalGameNameInConfig,
+ IsCacheUpdateEnabled = GamePreset.IsCacheUpdateEnabled,
+ IsConvertible = GamePreset.IsConvertible,
+ IsExperimental = GamePreset.IsExperimental,
+ IsGenshin = GamePreset.IsGenshin,
+ IsHideSocMedDesc = GamePreset.IsHideSocMedDesc,
+ IsRepairEnabled = GamePreset.IsRepairEnabled,
+ LauncherResourceURL = GamePreset.LauncherResourceURL,
+ LauncherSpriteURL = GamePreset.LauncherSpriteURL,
+ LauncherSpriteURLMultiLang = GamePreset.LauncherSpriteURLMultiLang,
+ LauncherSpriteURLMultiLangFallback = GamePreset.LauncherSpriteURLMultiLangFallback,
+ ProfileName = GamePreset.ProfileName,
+ ProtoDispatchKey = GamePreset.ProtoDispatchKey,
+ SteamGameID = GamePreset.SteamGameID,
+ SteamInstallRegistryLocation = GamePreset.SteamInstallRegistryLocation,
+ UseRightSideProgress = GamePreset.UseRightSideProgress,
+ VendorType = GamePreset.VendorType,
+ ZoneDescription = GamePreset.ZoneDescription,
+ ZoneFullname = GamePreset.ZoneFullname,
+ ZoneLogoURL = GamePreset.ZoneLogoURL,
+ ZoneName = GamePreset.ZoneName,
+ ZonePosterURL = GamePreset.ZonePosterURL,
+ ZoneURL = GamePreset.ZoneURL,
+ };
+ #endregion
+
+ internal RegionResourceProp _APIResouceProp { get; set; }
+ internal PresetConfigV2 _GamePreset { get; set; }
+ internal IGameSettings _GameSettings { get; set; }
+ internal IRepair _GameRepair { get; set; }
+ internal ICache _GameCache { get; set; }
+ internal IGameVersionCheck _GameVersion { get; set; }
+ internal IGameInstallManager _GameInstall { get; set; }
+ }
+
+ internal static class GamePropertyVault
+ {
+ private static Dictionary Vault = new Dictionary();
+ public static int LastGameHashID { get; set; }
+ public static int CurrentGameHashID { get; set; }
+ public static GamePresetProperty GetCurrentGameProperty() => Vault[CurrentGameHashID];
+
+ public static void LoadGameProperty(UIElement UIElementParent, RegionResourceProp APIResouceProp, PresetConfigV2 GamePreset)
+ {
+ LastGameHashID = LastGameHashID == 0 ? GamePreset.HashID : LastGameHashID;
+ CurrentGameHashID = GamePreset.HashID;
+ RegisterGameProperty(UIElementParent, APIResouceProp, GamePreset);
+ }
+
+ public static void RegisterGameProperty(UIElement UIElementParent, RegionResourceProp APIResouceProp, PresetConfigV2 GamePreset)
+ {
+ CleanupUnusedGameProperty();
+ if (Vault.ContainsKey(GamePreset.HashID))
+ {
+#if DEBUG
+ Logger.LogWriteLine($"[GamePropertyVault] Game property has been cached by Hash ID: {GamePreset.HashID}", LogType.Debug, true);
+#endif
+ return;
+ }
+
+ GamePresetProperty Property = new GamePresetProperty(UIElementParent, APIResouceProp, GamePreset);
+ Vault.Add(GamePreset.HashID, Property);
+#if DEBUG
+ Logger.LogWriteLine($"[GamePropertyVault] Creating & caching game property by Hash ID: {GamePreset.HashID}", LogType.Debug, true);
+#endif
+ }
+
+ private static void CleanupUnusedGameProperty()
+ {
+ if (Vault.Count == 0) return;
+
+ int[] unusedGamePropertyHashID = Vault.Values
+ .Where(x => !x._GameInstall.IsRunning && x._GamePreset.HashID != CurrentGameHashID)?
+ .Select(x => x._GamePreset.HashID)?
+ .ToArray();
+
+ foreach (int key in unusedGamePropertyHashID)
+ {
+#if DEBUG
+ Logger.LogWriteLine($"[GamePropertyVault] Cleaning up unused game property by Hash ID: {key}", LogType.Debug, true);
+#endif
+ Vault.Remove(key);
+ }
+ }
+
+ public static void AttachNotifForCurrentGame(int hashID = int.MinValue)
+ {
+ if (hashID < 0) hashID = CurrentGameHashID;
+ if (Vault.ContainsKey(hashID)) AttachNotifForCurrentGame_Inner(hashID);
+ }
+
+ private static void AttachNotifForCurrentGame_Inner(int HashID)
+ {
+ GamePresetProperty GameProperty = Vault[HashID];
+ if (GameProperty._GameInstall.IsRunning)
+ {
+ string actTitle = $"Downloading game: {GameProperty._GameVersion.GamePreset.GameName}";
+ string actSubtitle = GameProperty._GameVersion.GamePreset.ZoneName;
+ BackgroundActivityManager.Attach(HashID, GameProperty._GameInstall, actTitle, actSubtitle);
+ }
+ }
+
+ public static void DetachNotifForCurrentGame(int hashID = int.MinValue)
+ {
+ if (hashID < 0) hashID = CurrentGameHashID;
+ if (Vault.ContainsKey(hashID)) BackgroundActivityManager.Detach(hashID);
+ }
+ }
+
internal partial class PageStatics
{
- internal static IGameSettings _GameSettings { get; set; }
- internal static IRepair _GameRepair { get; set; }
- internal static ICache _GameCache { get; set; }
- internal static IGameVersionCheck _GameVersion { get; set; }
- internal static IGameInstallManager _GameInstall { get; set; }
internal static CommunityToolsProperty _CommunityToolsProperty { get; set; }
}
}
diff --git a/CollapseLauncher/Classes/Properties/InnerLauncherConfig.cs b/CollapseLauncher/Classes/Properties/InnerLauncherConfig.cs
index b31ae1a57..dc8ef841c 100644
--- a/CollapseLauncher/Classes/Properties/InnerLauncherConfig.cs
+++ b/CollapseLauncher/Classes/Properties/InnerLauncherConfig.cs
@@ -142,7 +142,7 @@ public static void SaveLocalNotificationData()
RegionPushIgnoreMsgIds = NotificationData.RegionPushIgnoreMsgIds
};
File.WriteAllText(AppNotifIgnoreFile,
- JsonSerializer.Serialize(LocalNotificationData, typeof(NotificationPush), NotificationPushContext.Default));
+ JsonSerializer.Serialize(LocalNotificationData, typeof(NotificationPush), InternalAppJSONContext.Default));
}
public static void LoadLocalNotificationData()
@@ -151,10 +151,10 @@ public static void LoadLocalNotificationData()
File.WriteAllText(AppNotifIgnoreFile,
JsonSerializer.Serialize(new NotificationPush(),
typeof(NotificationPush),
- NotificationPushContext.Default));
+ InternalAppJSONContext.Default));
string Data = File.ReadAllText(AppNotifIgnoreFile);
- NotificationPush LocalNotificationData = (NotificationPush)JsonSerializer.Deserialize(Data, typeof(NotificationPush), NotificationPushContext.Default);
+ NotificationPush LocalNotificationData = (NotificationPush)JsonSerializer.Deserialize(Data, typeof(NotificationPush), InternalAppJSONContext.Default);
NotificationData.AppPushIgnoreMsgIds = LocalNotificationData.AppPushIgnoreMsgIds;
NotificationData.RegionPushIgnoreMsgIds = LocalNotificationData.RegionPushIgnoreMsgIds;
NotificationData.CurrentShowMsgIds = LocalNotificationData.CurrentShowMsgIds;
@@ -172,7 +172,12 @@ public static async Task CheckForNewConfigV2()
{
await FallbackCDNUtil.DownloadCDNFallbackContent(_http, s, string.Format(AppGameConfigV2URLPrefix, (IsPreview ? "preview" : "stable") + "stamp"), default).ConfigureAwait(false);
s.Position = 0;
- ConfigStamp = (Stamp)JsonSerializer.Deserialize(s, typeof(Stamp), StampContext.Default);
+ ConfigStamp = (Stamp)JsonSerializer.Deserialize(s, typeof(Stamp), CoreLibraryJSONContext.Default);
+#if DEBUG
+ LogWriteLine($"Checking for metadata update...\r\n" +
+ $" LocalStamp : {ConfigV2LastUpdate}\r\n" +
+ $" RemoteStamp : {ConfigStamp?.LastUpdated}", LogType.Warning, true);
+#endif
}
}
catch (Exception ex)
@@ -181,7 +186,7 @@ public static async Task CheckForNewConfigV2()
return false;
}
- return ConfigV2LastUpdate != ConfigStamp?.LastUpdated;
+ return ConfigV2LastUpdate < ConfigStamp?.LastUpdated;
}
public static async Task DownloadConfigV2Files(bool Stamp, bool Content)
diff --git a/CollapseLauncher/Classes/Properties/WindowSizeProp/WindowSizeProp.cs b/CollapseLauncher/Classes/Properties/WindowSizeProp/WindowSizeProp.cs
index 71b245360..a808242bb 100644
--- a/CollapseLauncher/Classes/Properties/WindowSizeProp/WindowSizeProp.cs
+++ b/CollapseLauncher/Classes/Properties/WindowSizeProp/WindowSizeProp.cs
@@ -15,7 +15,7 @@ internal static class WindowSize
"Normal",
new WindowSizeProp()
{
- WindowBounds = new Size(1196, 726),
+ WindowBounds = new Size(1243, 726),
EventPostCarouselBounds = new Size(399, 185),
PostPanelBounds = new Size(399, 134),
PostPanelBottomMargin = new Thickness(0, 0, 0, 52),
diff --git a/CollapseLauncher/Classes/RegionManagement/FallbackCDNUtil.cs b/CollapseLauncher/Classes/RegionManagement/FallbackCDNUtil.cs
index ef1edf323..38188154f 100644
--- a/CollapseLauncher/Classes/RegionManagement/FallbackCDNUtil.cs
+++ b/CollapseLauncher/Classes/RegionManagement/FallbackCDNUtil.cs
@@ -6,7 +6,12 @@
using System;
using System.IO;
using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Runtime.Serialization;
using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using static Hi3Helper.Logger;
@@ -76,6 +81,7 @@ private string GetRelativePathOnly(string url)
internal static class FallbackCDNUtil
{
+ private static HttpClient _client = new HttpClient();
public static event EventHandler DownloadProgress;
public static async Task DownloadCDNFallbackContent(Http httpInstance, string outputPath, int parallelThread, string relativeURL, CancellationToken token)
@@ -239,10 +245,22 @@ public static CDNURLProperty GetPreferredCDN()
{
// Get the CurrentCDN index
int cdnIndex = GetAppConfigValue("CurrentCDN").ToInt();
+
+ // Fallback to the first CDN if index < 0 or > length of the list
+ if (cdnIndex < 0 || cdnIndex > CDNList.Count - 1) cdnIndex = 0;
+
// Return the CDN property as per index
return CDNList[cdnIndex];
}
+ public static async ValueTask DownloadAsJSONType(string URL, JsonSerializerContext context, CancellationToken token) =>
+ await _client.GetFromJsonAsync(URL, new JsonSerializerOptions()
+ {
+ TypeInfoResolver = context
+ }, token);
+
+ public static async ValueTask DownloadAsStream(string URL, CancellationToken token) => await _client.GetStreamAsync(URL, token);
+
// Re-send the events to the static DownloadProgress
private static void HttpInstance_DownloadProgressAdapter(object sender, DownloadEvent e) => DownloadProgress?.Invoke(sender, e);
}
diff --git a/CollapseLauncher/Classes/RegionManagement/RegionManagement.cs b/CollapseLauncher/Classes/RegionManagement/RegionManagement.cs
index 7b4f7f15e..00ee38316 100644
--- a/CollapseLauncher/Classes/RegionManagement/RegionManagement.cs
+++ b/CollapseLauncher/Classes/RegionManagement/RegionManagement.cs
@@ -15,6 +15,7 @@
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@@ -34,7 +35,7 @@ private enum ResourceLoadingType
DownloadInformation
}
- private Http _httpClient;
+ private GamePresetProperty CurrentGameProperty;
private bool IsLoadRegionComplete;
private bool IsExplicitCancel;
private string PreviousTag = string.Empty;
@@ -50,55 +51,56 @@ private enum ResourceLoadingType
public async Task LoadRegionFromCurrentConfigV2(PresetConfigV2 preset)
{
- using (_httpClient = new Http(default, 4, 250))
- {
- IsExplicitCancel = false;
- RegionToChangeName = $"{CurrentConfigV2GameCategory} - {CurrentConfigV2GameRegion}";
- LogWriteLine($"Initializing {RegionToChangeName}...", Hi3Helper.LogType.Scheme, true);
+ IsExplicitCancel = false;
+ RegionToChangeName = $"{CurrentConfigV2GameCategory} - {CurrentConfigV2GameRegion}";
+ LogWriteLine($"Initializing {RegionToChangeName}...", Hi3Helper.LogType.Scheme, true);
- // Set IsLoadRegionComplete to false
- IsLoadRegionComplete = false;
+ // Set IsLoadRegionComplete to false
+ IsLoadRegionComplete = false;
- // Clear MainPage State, like NavigationView, Load State, etc.
- ClearMainPageState();
+ // Clear MainPage State, like NavigationView, Load State, etc.
+ ClearMainPageState();
- // Load Region Resource from Launcher API
- bool IsLoadLocalizedResourceSuccess = await TryLoadResourceInfo(ResourceLoadingType.LocalizedResource, preset);
- bool IsLoadResourceRegionSuccess = false;
- if (IsLoadLocalizedResourceSuccess)
- {
- IsLoadResourceRegionSuccess = await TryLoadResourceInfo(ResourceLoadingType.DownloadInformation, preset);
- }
+ // Load Region Resource from Launcher API
+ bool IsLoadLocalizedResourceSuccess = await TryLoadResourceInfo(ResourceLoadingType.LocalizedResource, preset);
+ bool IsLoadResourceRegionSuccess = false;
+ if (IsLoadLocalizedResourceSuccess)
+ {
+ IsLoadResourceRegionSuccess = await TryLoadResourceInfo(ResourceLoadingType.DownloadInformation, preset);
+ }
- if (IsExplicitCancel)
+ if (IsExplicitCancel)
+ {
+ // If explicit cancel was triggered, restore the navigation menu item then return false
+ foreach (object item in LastNavigationItem)
{
- // If explicit cancel was triggered, restore the navigation menu item then return false
- foreach (object item in LastNavigationItem)
- {
- NavigationViewControl.MenuItems.Add(item);
- }
- NavigationViewControl.IsSettingsVisible = true;
- regionNewsProp = LastRegionNewsProp.Copy();
- LastRegionNewsProp = null;
- LastNavigationItem.Clear();
- return false;
+ NavigationViewControl.MenuItems.Add(item);
}
+ NavigationViewControl.IsSettingsVisible = true;
+ regionNewsProp = LastRegionNewsProp.Copy();
+ LastRegionNewsProp = null;
+ LastNavigationItem.Clear();
+ return false;
+ }
- if (!IsLoadLocalizedResourceSuccess || !IsLoadResourceRegionSuccess)
- {
- MainFrameChanger.ChangeWindowFrame(typeof(DisconnectedPage));
- return false;
- }
+ if (!IsLoadLocalizedResourceSuccess || !IsLoadResourceRegionSuccess)
+ {
+ MainFrameChanger.ChangeWindowFrame(typeof(DisconnectedPage));
+ return false;
+ }
- // Finalize Region Load
- await ChangeBackgroundImageAsRegion();
- FinalizeLoadRegion(preset);
+ // Finalize Region Load
+ await ChangeBackgroundImageAsRegion();
+ FinalizeLoadRegion(preset);
+ CurrentGameProperty = GamePropertyVault.GetCurrentGameProperty();
- // Set IsLoadRegionComplete to false
- IsLoadRegionComplete = true;
+ GamePropertyVault.AttachNotifForCurrentGame(GamePropertyVault.LastGameHashID);
+ GamePropertyVault.DetachNotifForCurrentGame(GamePropertyVault.CurrentGameHashID);
- return true;
- }
+ // Set IsLoadRegionComplete to false
+ IsLoadRegionComplete = true;
+
+ return true;
}
public void ClearMainPageState()
@@ -108,6 +110,9 @@ public void ClearMainPageState()
NavigationViewControl.MenuItems.Clear();
NavigationViewControl.IsSettingsVisible = false;
PreviousTag = "launcher";
+ PreviousTagString.Clear();
+ PreviousTagString.Add(PreviousTag);
+ LauncherFrame.BackStack.Clear();
ResetRegionProp();
}
@@ -162,6 +167,168 @@ private async ValueTask TryLoadResourceInfo(ResourceLoadingType resourceTy
return false;
}
+ private async ValueTask FetchLauncherLocalizedResources(CancellationToken Token, PresetConfigV2 Preset)
+ {
+ regionBackgroundProp = Preset.LauncherSpriteURLMultiLang ?
+ await TryGetMultiLangResourceProp(Token, Preset) :
+ await TryGetSingleLangResourceProp(Token, Preset);
+
+ await DownloadBackgroundImage(Token);
+
+ await GetLauncherAdvInfo(Token, Preset);
+ await GetLauncherCarouselInfo(Token);
+ await GetLauncherEventInfo(Token);
+ GetLauncherPostInfo();
+ }
+
+ private async ValueTask DownloadBackgroundImage(CancellationToken Token)
+ {
+ regionBackgroundProp.imgLocalPath = Path.Combine(AppGameImgFolder, "bg", Path.GetFileName(regionBackgroundProp.data.adv.background));
+ SetAndSaveConfigValue("CurrentBackground", regionBackgroundProp.imgLocalPath);
+
+ if (!Directory.Exists(Path.Combine(AppGameImgFolder, "bg")))
+ Directory.CreateDirectory(Path.Combine(AppGameImgFolder, "bg"));
+
+ FileInfo fI = new FileInfo(regionBackgroundProp.imgLocalPath);
+ if (fI.Exists) return;
+
+ using (Stream netStream = await FallbackCDNUtil.DownloadAsStream(regionBackgroundProp.data.adv.background, Token))
+ using (Stream outStream = fI.Create())
+ {
+ netStream.CopyTo(outStream);
+ }
+ }
+
+ private async ValueTask FetchLauncherDownloadInformation(CancellationToken token, PresetConfigV2 Preset)
+ {
+ _gameAPIProp = await FallbackCDNUtil.DownloadAsJSONType(Preset.LauncherResourceURL, CoreLibraryJSONContext.Default, token);
+#if DEBUG
+ if (_gameAPIProp.data.game.latest.decompressed_path != null) LogWriteLine($"Decompressed Path: {_gameAPIProp.data.game.latest.decompressed_path}", LogType.Default, true);
+ if (_gameAPIProp.data.game.latest.path != null) LogWriteLine($"ZIP Path: {_gameAPIProp.data.game.latest.path}", LogType.Default, true);
+ if (_gameAPIProp.data.pre_download_game?.latest?.decompressed_path != null) LogWriteLine($"Decompressed Path Pre-load: {_gameAPIProp.data.pre_download_game?.latest?.decompressed_path}", LogType.Default, true);
+ if (_gameAPIProp.data.pre_download_game?.latest?.path != null) LogWriteLine($"ZIP Path Pre-load: {_gameAPIProp.data.pre_download_game?.latest?.path}", LogType.Default, true);
+#endif
+ }
+
+ private async ValueTask TryGetMultiLangResourceProp(CancellationToken Token, PresetConfigV2 Preset)
+ {
+ RegionResourceProp ret = await GetMultiLangResourceProp(Lang.LanguageID.ToLower(), Token, Preset);
+
+ return ret.data.adv == null
+ || ((ret.data.adv.version ?? 5) <= 4
+ && Preset.GameType == GameType.Honkai) ?
+ await GetMultiLangResourceProp(Preset.LauncherSpriteURLMultiLangFallback ?? "en-us", Token, Preset) :
+ ret;
+ }
+
+ private async ValueTask GetMultiLangResourceProp(string langID, CancellationToken token, PresetConfigV2 Preset)
+ => await FallbackCDNUtil.DownloadAsJSONType(string.Format(Preset.LauncherSpriteURL, langID), CoreLibraryJSONContext.Default, token);
+
+
+ private async ValueTask TryGetSingleLangResourceProp(CancellationToken token, PresetConfigV2 Preset)
+ => await FallbackCDNUtil.DownloadAsJSONType(Preset.LauncherSpriteURL, CoreLibraryJSONContext.Default, token);
+
+ private void ResetRegionProp()
+ {
+ LastRegionNewsProp = regionNewsProp.Copy();
+ regionNewsProp = new HomeMenuPanel()
+ {
+ sideMenuPanel = null,
+ imageCarouselPanel = null,
+ articlePanel = null,
+ eventPanel = null
+ };
+ }
+
+ private async ValueTask GetLauncherAdvInfo(CancellationToken Token, PresetConfigV2 Preset)
+ {
+ if (regionBackgroundProp.data.icon.Count == 0) return;
+
+ regionNewsProp.sideMenuPanel = new List();
+ foreach (RegionSocMedProp item in regionBackgroundProp.data.icon)
+ {
+ regionNewsProp.sideMenuPanel.Add(new MenuPanelProp
+ {
+ URL = item.url,
+ Icon = await GetCachedSprites(item.img, Token),
+ IconHover = await GetCachedSprites(item.img_hover, Token),
+ QR = string.IsNullOrEmpty(item.qr_img) ? null : await GetCachedSprites(item.qr_img, Token),
+ QR_Description = string.IsNullOrEmpty(item.qr_desc) ? null : item.qr_desc,
+ Description = string.IsNullOrEmpty(item.title) || Preset.IsHideSocMedDesc ? item.url : item.title
+ });
+ }
+ }
+
+ private async ValueTask GetLauncherCarouselInfo(CancellationToken Token)
+ {
+ if (regionBackgroundProp.data.banner.Count == 0) return;
+
+ regionNewsProp.imageCarouselPanel = new List();
+ foreach (RegionSocMedProp item in regionBackgroundProp.data.banner)
+ {
+ regionNewsProp.imageCarouselPanel.Add(new MenuPanelProp
+ {
+ URL = item.url,
+ Icon = await GetCachedSprites(item.img, Token),
+ Description = string.IsNullOrEmpty(item.name) ? item.url : item.name
+ });
+ }
+ }
+
+ private async ValueTask GetLauncherEventInfo(CancellationToken Token)
+ {
+ if (string.IsNullOrEmpty(regionBackgroundProp.data.adv.icon)) return;
+
+ regionNewsProp.eventPanel = new RegionBackgroundProp
+ {
+ url = regionBackgroundProp.data.adv.url,
+ icon = await GetCachedSprites(regionBackgroundProp.data.adv.icon, Token)
+ };
+ }
+
+ private void GetLauncherPostInfo()
+ {
+ if (regionBackgroundProp.data.post.Count == 0) return;
+
+ regionNewsProp.articlePanel = new PostCarouselTypes();
+ foreach (RegionSocMedProp item in regionBackgroundProp.data.post)
+ {
+ switch (item.type)
+ {
+ case PostCarouselType.POST_TYPE_ACTIVITY:
+ regionNewsProp.articlePanel.Events.Add(item);
+ break;
+ case PostCarouselType.POST_TYPE_ANNOUNCE:
+ regionNewsProp.articlePanel.Notices.Add(item);
+ break;
+ case PostCarouselType.POST_TYPE_INFO:
+ regionNewsProp.articlePanel.Info.Add(item);
+ break;
+ }
+ }
+ }
+
+ public async ValueTask GetCachedSprites(string URL, CancellationToken token)
+ {
+ string cacheFolder = Path.Combine(AppGameImgFolder, "cache");
+ string cachePath = Path.Combine(cacheFolder, Path.GetFileNameWithoutExtension(URL));
+ if (!Directory.Exists(cacheFolder))
+ Directory.CreateDirectory(cacheFolder);
+
+ FileInfo fInfo = new FileInfo(cachePath);
+
+ if (!fInfo.Exists || fInfo.Length < (1 << 10))
+ {
+ using (FileStream fs = fInfo.Create())
+ using (Stream netStream = await FallbackCDNUtil.DownloadAsStream(URL, token))
+ {
+ netStream.CopyTo(fs);
+ }
+ }
+
+ return cachePath;
+ }
+
private uint SendTimeoutCancelationMessage(Exception ex, uint currentTimeout)
{
DispatcherQueue.TryEnqueue(() =>
@@ -201,7 +368,7 @@ private async void WatchAndCancelIfTimeout(CancellationTokenSource TokenSource,
private void FinalizeLoadRegion(PresetConfigV2 preset)
{
// Log if region has been successfully loaded
- LogWriteLine($"Initializing Region {preset.ZoneFullname} Done!", Hi3Helper.LogType.Scheme, true);
+ LogWriteLine($"Initializing Region {preset.ZoneFullname} Done!", LogType.Scheme, true);
// Initializing Game Statics
LoadGameStaticsByGameType(preset);
@@ -215,59 +382,22 @@ private void FinalizeLoadRegion(PresetConfigV2 preset)
private void LoadGameStaticsByGameType(PresetConfigV2 preset)
{
+ GamePropertyVault.AttachNotifForCurrentGame();
DisposeAllPageStatics();
- switch (preset.GameType)
- {
- case GameType.Honkai:
- // TEMP:
- // This is used to handle FallbackGameType
- if (preset.FallbackGameType == GameType.StarRail)
- {
- PageStatics._GameVersion = new GameTypeStarRailVersion(this, _gameAPIProp, preset);
- PageStatics._GameSettings = new StarRailSettings();
- PageStatics._GameCache = null;
- PageStatics._GameRepair = null;
- PageStatics._GameInstall = new StarRailInstall(this);
-
- preset.GameType = GameType.StarRail;
- }
- else
- {
- PageStatics._GameVersion = new GameTypeHonkaiVersion(this, _gameAPIProp, preset);
- PageStatics._GameSettings = new HonkaiSettings();
- PageStatics._GameCache = new HonkaiCache(this);
- PageStatics._GameRepair = new HonkaiRepair(this);
- PageStatics._GameInstall = new HonkaiInstall(this);
- }
- break;
- case GameType.Genshin:
- PageStatics._GameVersion = new GameTypeGenshinVersion(this, _gameAPIProp, preset);
- PageStatics._GameSettings = new GenshinSettings();
- PageStatics._GameCache = null;
- PageStatics._GameRepair = new GenshinRepair(this, PageStatics._GameVersion.GameAPIProp.data.game.latest.decompressed_path);
- PageStatics._GameInstall = new GenshinInstall(this);
- break;
- case GameType.StarRail:
- PageStatics._GameVersion = new GameTypeStarRailVersion(this, _gameAPIProp, preset);
- PageStatics._GameSettings = new StarRailSettings();
- PageStatics._GameCache = new StarRailCache(this);
- PageStatics._GameRepair = new StarRailRepair(this);
- PageStatics._GameInstall = new StarRailInstall(this);
- break;
- }
+ GamePropertyVault.LoadGameProperty(this, _gameAPIProp, preset);
// Spawn Region Notification
- SpawnRegionNotification(PageStatics._GameVersion.GamePreset.ProfileName);
+ SpawnRegionNotification(preset.ProfileName);
}
private void DisposeAllPageStatics()
{
- PageStatics._GameInstall?.CancelRoutine();
- PageStatics._GameRepair?.CancelRoutine();
- PageStatics._GameRepair?.Dispose();
- PageStatics._GameCache?.CancelRoutine();
- PageStatics._GameCache?.Dispose();
+ // CurrentGameProperty._GameInstall?.CancelRoutine();
+ CurrentGameProperty?._GameRepair?.CancelRoutine();
+ CurrentGameProperty?._GameRepair?.Dispose();
+ CurrentGameProperty?._GameCache?.CancelRoutine();
+ CurrentGameProperty?._GameCache?.Dispose();
#if DEBUG
LogWriteLine("Page statics have been disposed!", LogType.Debug, true);
#endif
@@ -330,6 +460,7 @@ private async void ChangeRegionNoWarning(object sender, RoutedEventArgs e)
await LoadRegionRootButton();
HideLoadingPopup(true, Lang._MainPage.RegionLoadingTitle, RegionToChangeName);
MainFrameChanger.ChangeMainFrame(m_appMode == AppMode.Hi3CacheUpdater ? typeof(CachesPage) : typeof(HomePage));
+ LauncherFrame.BackStack.Clear();
}
private async void ChangeRegion(object sender, RoutedEventArgs e)
@@ -385,6 +516,7 @@ private void ToggleChangeRegionBtn(in object sender, bool IsHide)
ChangeRegionConfirmProgressBar.Visibility = Visibility.Collapsed;
HideLoadingPopup(true, Lang._MainPage.RegionLoadingTitle, RegionToChangeName);
MainFrameChanger.ChangeMainFrame(m_appMode == AppMode.Hi3CacheUpdater ? typeof(CachesPage) : typeof(HomePage));
+ LauncherFrame.BackStack.Clear();
}
(sender as Button).IsEnabled = !IsHide;
diff --git a/CollapseLauncher/Classes/RegistryMonitor/RegistryMonitor.cs b/CollapseLauncher/Classes/RegistryMonitor/RegistryMonitor.cs
index 8e294c144..7e98888b4 100644
--- a/CollapseLauncher/Classes/RegistryMonitor/RegistryMonitor.cs
+++ b/CollapseLauncher/Classes/RegistryMonitor/RegistryMonitor.cs
@@ -15,6 +15,7 @@
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32;
+using static Hi3Helper.Logger;
namespace RegistryUtils
{
@@ -144,6 +145,11 @@ public RegistryMonitor(string name)
public RegistryMonitor(RegistryHive registryHive, string subKey)
{
InitRegistryKey(registryHive, subKey);
+#if DEBUG
+ LogWriteLine($"RegistryMonitor Initialized!\r\n" +
+ $" Hive: {registryHive}\r\n" +
+ $" subKey: {subKey}", Hi3Helper.LogType.Debug, true);
+#endif
}
///
@@ -154,6 +160,9 @@ public void Dispose()
Stop();
_disposed = true;
GC.SuppressFinalize(this);
+#if DEBUG
+ LogWriteLine($"RegistryMonitor Disposed!", Hi3Helper.LogType.Debug, true);
+#endif
}
///
@@ -333,6 +342,11 @@ private void ThreadLoop()
if (WaitHandle.WaitAny(waitHandles) == 0)
{
+#if DEBUG
+ LogWriteLine($"[RegistryMonitor] Found change(s) in registry!\r\n" +
+ $" Hive: {_registryHive}\r\n" +
+ $" subName: {_registrySubName}", Hi3Helper.LogType.Debug, true);
+#endif
OnRegChanged();
}
}
diff --git a/CollapseLauncher/Classes/RepairManagement/Genshin/Check.cs b/CollapseLauncher/Classes/RepairManagement/Genshin/Check.cs
index e0ccfde73..032b7a134 100644
--- a/CollapseLauncher/Classes/RepairManagement/Genshin/Check.cs
+++ b/CollapseLauncher/Classes/RepairManagement/Genshin/Check.cs
@@ -74,7 +74,7 @@ private void TryMoveAudioPersistent()
if (!Directory.Exists(audioPersistentPath)) return;
if (!Directory.Exists(audioAsbPath)) Directory.CreateDirectory(audioAsbPath);
- List audioLangList = ((GameTypeGenshinVersion)PageStatics._GameVersion)._audioVoiceLanguageList;
+ List audioLangList = ((GameTypeGenshinVersion)_gameVersionManager)._audioVoiceLanguageList;
foreach (string path in Directory.EnumerateDirectories(audioPersistentPath, "*", SearchOption.TopDirectoryOnly))
{
string langName = Path.GetFileName(path);
diff --git a/CollapseLauncher/Classes/RepairManagement/Genshin/Fetch.cs b/CollapseLauncher/Classes/RepairManagement/Genshin/Fetch.cs
index 2790c3da5..02eaab8d3 100644
--- a/CollapseLauncher/Classes/RepairManagement/Genshin/Fetch.cs
+++ b/CollapseLauncher/Classes/RepairManagement/Genshin/Fetch.cs
@@ -66,7 +66,7 @@ private async ValueTask> Fetch(List EliminateUnnecessaryAssetIndex(List assetIndex)
{
// Section: Eliminate unused audio files
- List audioLangList = (PageStatics._GameVersion as GameTypeGenshinVersion)._audioVoiceLanguageList;
+ List audioLangList = (_gameVersionManager as GameTypeGenshinVersion)._audioVoiceLanguageList;
string audioLangListPath = Path.Combine(_gamePath, $"{_execPrefix}_Data", "Persistent", "audio_lang_14");
// Get the list of audio lang list
@@ -214,7 +214,7 @@ private void ParsePersistentManifest(string localManifestPath,
while (!reader.EndOfStream)
{
string manifestLine = reader.ReadLine();
- PkgVersionProperties manifestEntry = (PkgVersionProperties)JsonSerializer.Deserialize(manifestLine, typeof(PkgVersionProperties), PkgVersionPropertiesContext.Default);
+ PkgVersionProperties manifestEntry = (PkgVersionProperties)JsonSerializer.Deserialize(manifestLine, typeof(PkgVersionProperties), CoreLibraryJSONContext.Default);
// Ignore if the remote name is "svc_catalog" or "ctable.dat"
if (Path.GetFileName(manifestEntry.remoteName).Equals("svc_catalog", StringComparison.OrdinalIgnoreCase) ||
@@ -301,7 +301,7 @@ private void SavePersistentRevision(QueryProperty dispatchQuery)
private async Task GetDispatcherQuery(Http _httpClient, CancellationToken token)
{
// Initialize dispatch helper
- using (GenshinDispatchHelper dispatchHelper = new GenshinDispatchHelper(_dispatcherRegionID, _gamePreset.ProtoDispatchKey, _dispatcherURL, _gameVersion.VersionString, token))
+ using (GenshinDispatchHelper dispatchHelper = new GenshinDispatchHelper(_dispatcherRegionID, _gameVersionManager.GamePreset.ProtoDispatchKey, _dispatcherURL, _gameVersion.VersionString, token))
{
// Get the master decryptor
YSDispatchDec dispatchDecryptor = InitializeMasterDecryptor();
@@ -418,7 +418,7 @@ private void ParseManifestToAssetIndex(string manifestPath, List x.EndsWith(acceptedExtension, StringComparison.OrdinalIgnoreCase)))
{
// Deserialize JSON line into local entry.
- entry = (PkgVersionProperties)JsonSerializer.Deserialize(data, typeof(PkgVersionProperties), PkgVersionPropertiesContext.Default);
+ entry = (PkgVersionProperties)JsonSerializer.Deserialize(data, typeof(PkgVersionProperties), CoreLibraryJSONContext.Default);
// If the parent path is not defined, then use already-defined parent path from JSON and append it as remote name.
if (!string.IsNullOrEmpty(parentPath))
diff --git a/CollapseLauncher/Classes/RepairManagement/Genshin/GenshinRepair.cs b/CollapseLauncher/Classes/RepairManagement/Genshin/GenshinRepair.cs
index 6215dfec0..5097856b7 100644
--- a/CollapseLauncher/Classes/RepairManagement/Genshin/GenshinRepair.cs
+++ b/CollapseLauncher/Classes/RepairManagement/Genshin/GenshinRepair.cs
@@ -21,21 +21,21 @@ internal partial class GenshinRepair :
ProgressBase, IRepair
{
#region ExtensionProperties
- private protected string _execPrefix { get => Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName); }
+ private protected string _execPrefix { get => Path.GetFileNameWithoutExtension(_gameVersionManager.GamePreset.GameExecutableName); }
private protected int _dispatcherRegionID { get; init; }
- private protected string _dispatcherURL { get => _gamePreset.GameDispatchURL ?? ""; }
- private protected string _dispatcherKey { get => _gamePreset.DispatcherKey ?? ""; }
- private protected int _dispatcherKeyLength { get => _gamePreset.DispatcherKeyBitLength ?? 0x100; }
- private protected string _gamePersistentPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName)}_Data", "Persistent"); }
- private protected string _gameStreamingAssetsPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName)}_Data", "StreamingAssets"); }
+ private protected string _dispatcherURL { get => _gameVersionManager.GamePreset.GameDispatchURL ?? ""; }
+ private protected string _dispatcherKey { get => _gameVersionManager.GamePreset.DispatcherKey ?? ""; }
+ private protected int _dispatcherKeyLength { get => _gameVersionManager.GamePreset.DispatcherKeyBitLength ?? 0x100; }
+ private protected string _gamePersistentPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gameVersionManager.GamePreset.GameExecutableName)}_Data", "Persistent"); }
+ private protected string _gameStreamingAssetsPath { get => Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gameVersionManager.GamePreset.GameExecutableName)}_Data", "StreamingAssets"); }
private protected GenshinAudioLanguage _audioLanguage { get; init; }
#endregion
- public GenshinRepair(UIElement parentUI, string gameRepoURL)
- : base(parentUI, null, gameRepoURL, null)
+ public GenshinRepair(UIElement parentUI, IGameVersionCheck GameVersionManager, string gameRepoURL)
+ : base(parentUI, GameVersionManager, null, gameRepoURL, null)
{
- _audioLanguage = (GenshinAudioLanguage)_gamePreset.GetVoiceLanguageID();
- _dispatcherRegionID = _gamePreset.GetRegServerNameID();
+ _audioLanguage = (GenshinAudioLanguage)_gameVersionManager.GamePreset.GetVoiceLanguageID();
+ _dispatcherRegionID = _gameVersionManager.GamePreset.GetRegServerNameID();
}
~GenshinRepair() => Dispose();
diff --git a/CollapseLauncher/Classes/RepairManagement/Honkai/Check.cs b/CollapseLauncher/Classes/RepairManagement/Honkai/Check.cs
index 406ce8ef9..d0721922a 100644
--- a/CollapseLauncher/Classes/RepairManagement/Honkai/Check.cs
+++ b/CollapseLauncher/Classes/RepairManagement/Honkai/Check.cs
@@ -547,15 +547,19 @@ private void GetUnusedAssetIndexList(List catalog, List assetIndex, CancellationToke
// Check for manifest. If it doesn't exist, then throw and warn the user
if (!manifestDict.ContainsKey(_gameVersion.VersionString))
{
- throw new VersionNotFoundException($"Manifest for {_gamePreset.ZoneName} (version: {_gameVersion.VersionString}) doesn't exist! Please contact @neon-nyan or open an issue for this!");
+ throw new VersionNotFoundException($"Manifest for {_gameVersionManager.GamePreset.ZoneName} (version: {_gameVersion.VersionString}) doesn't exist! Please contact @neon-nyan or open an issue for this!");
}
// Assign the URL based on the version
@@ -276,14 +276,14 @@ private async Task> FetchMetadata(Http _httpClient, C
using (MemoryStream mfs = new MemoryStream())
{
// Set metadata URL
- string urlMetadata = string.Format(AppGameRepoIndexURLPrefix, _gamePreset.ProfileName);
+ string urlMetadata = string.Format(AppGameRepoIndexURLPrefix, _gameVersionManager.GamePreset.ProfileName);
// Start downloading metadata using FallbackCDNUtil
await FallbackCDNUtil.DownloadCDNFallbackContent(_httpClient, mfs, urlMetadata, token);
// Deserialize metadata
mfs.Position = 0;
- return (Dictionary)JsonSerializer.Deserialize(mfs, typeof(Dictionary), D_StringString.Default);
+ return (Dictionary)JsonSerializer.Deserialize(mfs, typeof(Dictionary), CoreLibraryJSONContext.Default);
}
}
@@ -293,7 +293,7 @@ private async Task FetchAssetIndex(Http _httpClient, List
using (MemoryStream mfs = new MemoryStream())
{
// Set asset index URL
- string urlIndex = string.Format(AppGameRepairIndexURLPrefix, _gamePreset.ProfileName, _gameVersion.VersionString) + ".bin";
+ string urlIndex = string.Format(AppGameRepairIndexURLPrefix, _gameVersionManager.GamePreset.ProfileName, _gameVersion.VersionString) + ".bin";
// Start downloading asset index using FallbackCDNUtil
await FallbackCDNUtil.DownloadCDNFallbackContent(_httpClient, mfs, urlIndex, token);
diff --git a/CollapseLauncher/Classes/RepairManagement/Honkai/HonkaiRepair.cs b/CollapseLauncher/Classes/RepairManagement/Honkai/HonkaiRepair.cs
index 5b2687735..aa8805aee 100644
--- a/CollapseLauncher/Classes/RepairManagement/Honkai/HonkaiRepair.cs
+++ b/CollapseLauncher/Classes/RepairManagement/Honkai/HonkaiRepair.cs
@@ -1,4 +1,5 @@
using CollapseLauncher.GameSettings.Honkai;
+using CollapseLauncher.GameVersioning;
using CollapseLauncher.Interfaces;
using CollapseLauncher.Statics;
using Hi3Helper.Data;
@@ -16,11 +17,10 @@ internal partial class HonkaiRepair :
ProgressBase, IRepair
{
#region Properties
- private HonkaiCache _cacheUtil = (PageStatics._GameCache as ICacheBase).AsBaseType();
-
private const ulong _assetIndexSignature = 0x657370616C6C6F43; // 657370616C6C6F43 is "Collapse"
private const string _assetBasePath = "BH3_Data/StreamingAssets/";
private readonly string[] _skippableAssets = new string[] { "CG_Temp.usm" };
+ private HonkaiCache _cacheUtil { get; init; }
private string _assetBaseURL { get; set; }
private string _blockBaseURL { get => ConverterTool.CombineURLFromString(_assetBaseURL, $"StreamingAsb/{string.Join('_', _gameVersion.VersionArray)}/pc/HD"); }
private string _blockAsbBaseURL { get => ConverterTool.CombineURLFromString(_blockBaseURL, "/asb"); }
@@ -41,21 +41,23 @@ internal partial class HonkaiRepair :
private protected List _originAssetIndex { get; set; }
#endregion
- public HonkaiRepair(UIElement parentUI, bool onlyRecoverMainAsset = false, string versionOverride = null)
- : base(parentUI, null, "", versionOverride)
+ public HonkaiRepair(UIElement parentUI, IGameVersionCheck GameVersionManager, ICache GameCacheManager, IGameSettings GameSettings, bool onlyRecoverMainAsset = false, string versionOverride = null)
+ : base(parentUI, GameVersionManager, GameSettings, null, "", versionOverride)
{
+ _cacheUtil = (GameCacheManager as ICacheBase).AsBaseType();
+
// Get flag to only recover main assets
_isOnlyRecoverMain = onlyRecoverMainAsset;
// Initialize audio asset language
- string audioLanguage = (PageStatics._GameSettings as HonkaiSettings).SettingsAudio._userCVLanguage;
+ string audioLanguage = (GameSettings as HonkaiSettings).SettingsAudio._userCVLanguage;
switch (audioLanguage)
{
case "Chinese(PRC)":
_audioLanguage = AudioLanguageType.Chinese;
break;
default:
- _audioLanguage = _gamePreset.GameDefaultCVLanguage;
+ _audioLanguage = _gameVersionManager.GamePreset.GameDefaultCVLanguage;
break;
}
}
diff --git a/CollapseLauncher/Classes/RepairManagement/StarRail/Check.cs b/CollapseLauncher/Classes/RepairManagement/StarRail/Check.cs
index 8f464b0d3..8a2549f4d 100644
--- a/CollapseLauncher/Classes/RepairManagement/StarRail/Check.cs
+++ b/CollapseLauncher/Classes/RepairManagement/StarRail/Check.cs
@@ -35,7 +35,7 @@ await Task.Run(() =>
RestartStopwatch();
// Get persistent and streaming paths
- string execName = Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName);
+ string execName = Path.GetFileNameWithoutExtension(_innerGameVersionManager.GamePreset.GameExecutableName);
string baseBlocksPathPersistent = Path.Combine(_gamePath, @$"{execName}_Data\Persistent\Asb\Windows");
string baseBlocksPathStreaming = Path.Combine(_gamePath, @$"{execName}_Data\StreamingAssets\Asb\Windows");
@@ -99,7 +99,29 @@ private void CheckAssetType(FilePropertiesRemote asset, List AssetEntry.Add(
+ new AssetProperty(
+ Path.GetFileName(fileInfoStreaming.FullName),
+ RepairAssetType.Unused,
+ Path.GetDirectoryName(fileInfoStreaming.FullName),
+ asset.S,
+ null,
+ null
+ )
+ ));
+ targetAssetIndex.Add(asset);
+
+ LogWriteLine($"File [T: {asset.FT}]: {asset.N} is redundant (exist both on persistent and streaming)", LogType.Warning, true);
+ }
// Check if both location has the file exist or has the size right
if (UsePersistent && !IsPersistentExist && !IsStreamingExist)
@@ -176,10 +198,21 @@ private void CheckAssetType(FilePropertiesRemote asset, List assetIndex, CancellationToke
try
{
// Subscribe the fetching progress and subscribe StarRailMetadataTool progress to adapter
- _gameVersionManager.StarRailMetadataTool.HttpEvent += _httpClient_FetchAssetProgress;
+ _innerGameVersionManager.StarRailMetadataTool.HttpEvent += _httpClient_FetchAssetProgress;
// Initialize the metadata tool (including dispatcher and gateway)
- await _gameVersionManager.StarRailMetadataTool.Initialize(token, GetExistingGameRegionID(), Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_gamePreset.GameExecutableName)}_Data\\Persistent"));
+ await _innerGameVersionManager.StarRailMetadataTool.Initialize(token, GetExistingGameRegionID(), Path.Combine(_gamePath, $"{Path.GetFileNameWithoutExtension(_innerGameVersionManager.GamePreset.GameExecutableName)}_Data\\Persistent"));
// Read block metadata and convert to FilePropertiesRemote
- await _gameVersionManager.StarRailMetadataTool.ReadAsbMetadataInformation(token);
- await _gameVersionManager.StarRailMetadataTool.ReadBlockMetadataInformation(token);
- ConvertSRMetadataToAssetIndex(_gameVersionManager.StarRailMetadataTool.MetadataBlock, assetIndex);
+ await _innerGameVersionManager.StarRailMetadataTool.ReadAsbMetadataInformation(token);
+ await _innerGameVersionManager.StarRailMetadataTool.ReadBlockMetadataInformation(token);
+ ConvertSRMetadataToAssetIndex(_innerGameVersionManager.StarRailMetadataTool.MetadataBlock, assetIndex);
// Read Audio metadata and convert to FilePropertiesRemote
- await _gameVersionManager.StarRailMetadataTool.ReadAudioMetadataInformation(token);
- ConvertSRMetadataToAssetIndex(_gameVersionManager.StarRailMetadataTool.MetadataAudio, assetIndex);
+ await _innerGameVersionManager.StarRailMetadataTool.ReadAudioMetadataInformation(token);
+ ConvertSRMetadataToAssetIndex(_innerGameVersionManager.StarRailMetadataTool.MetadataAudio, assetIndex, true);
// Read Video metadata and convert to FilePropertiesRemote
- await _gameVersionManager.StarRailMetadataTool.ReadVideoMetadataInformation(token);
- ConvertSRMetadataToAssetIndex(_gameVersionManager.StarRailMetadataTool.MetadataVideo, assetIndex);
+ await _innerGameVersionManager.StarRailMetadataTool.ReadVideoMetadataInformation(token);
+ ConvertSRMetadataToAssetIndex(_innerGameVersionManager.StarRailMetadataTool.MetadataVideo, assetIndex);
}
finally
{
// Unsubscribe the fetching progress and dispose it and unsubscribe cacheUtil progress to adapter
- _gameVersionManager.StarRailMetadataTool.HttpEvent -= _httpClient_FetchAssetProgress;
+ _innerGameVersionManager.StarRailMetadataTool.HttpEvent -= _httpClient_FetchAssetProgress;
}
}
@@ -56,37 +57,57 @@ private async Task Fetch(List assetIndex, CancellationToke
private unsafe string GetExistingGameRegionID()
{
#nullable enable
- object? value = GameSettings.Statics.RegistryRoot?.GetValue("App_LastServerName_h2577443795", null);
+ // Try get the value as nullable object
+ object? value = RegistryRoot?.GetValue("App_LastServerName_h2577443795", null);
+ // Check if the value is null, then return the default name
if (value == null)
{
- return _gamePreset.GameDispatchDefaultName ?? throw new KeyNotFoundException("Default dispatcher name in metadata is not exist!");
+ // Return the dispatch default name. If none, then throw
+ return _innerGameVersionManager.GamePreset.GameDispatchDefaultName ?? throw new KeyNotFoundException("Default dispatcher name in metadata is not exist!");
}
#nullable disable
- ReadOnlySpan span = (value as byte[]).AsSpan();
- fixed (byte* valueSpan = span)
- {
- string name = Encoding.UTF8.GetString(valueSpan, span.Length - 1);
- return name;
- }
+ // Cast the value as byte span
+ ReadOnlySpan span = ((byte[])value).AsSpan();
+ // Get the name from the span and trim the \0 character at the end
+ string name = Encoding.UTF8.GetString(span.Slice(0, span.Length - 1));
+ return name;
}
- private void ConvertSRMetadataToAssetIndex(SRMetadataBase metadata, List assetIndex)
+ private void ConvertSRMetadataToAssetIndex(SRMetadataBase metadata, List assetIndex, bool writeAudioLangRedord = false)
{
- int voLangID = _gamePreset.GetVoiceLanguageID();
- string voLangName = _gamePreset.GetStarRailVoiceLanguageFullNameByID(voLangID);
+ // Get the voice Lang ID
+ int voLangID = _innerGameVersionManager.GamePreset.GetVoiceLanguageID();
+ // Get the voice Lang name by ID
+ string voLangName = _innerGameVersionManager.GamePreset.GetStarRailVoiceLanguageFullNameByID(voLangID);
- IEnumerable srAssetEnumerateFiltered = metadata.GetAssets().AssetList;
+ // If prompt to write Redord file
+ if (writeAudioLangRedord)
+ {
+ // Get game executable name, directory and file path
+ string execName = Path.GetFileNameWithoutExtension(_innerGameVersionManager.GamePreset.GameExecutableName);
+ string audioRedordDir = Path.Combine(_gamePath, @$"{execName}_Data\Persistent\Audio\AudioPackage\Windows");
+ string audioRedordPath = Path.Combine(audioRedordDir, "AudioLangRedord.txt");
+
+ // Create the directory if not exist
+ if (!Directory.Exists(audioRedordDir)) Directory.CreateDirectory(audioRedordDir);
+ // Then write the Redord file content
+ File.WriteAllText(audioRedordPath, "{\"AudioLang\":\"" + voLangName + "\"}");
+ }
int count = 0;
long countSize = 0;
- foreach (SRAsset asset in srAssetEnumerateFiltered)
+ // Enumerate the Asset List
+ foreach (SRAsset asset in metadata.EnumerateAssets())
{
- if (IsAudioLangFile(asset, voLangName, out bool isHasHashMark))
- {
- string hash = HexTool.BytesToHexUnsafe(asset.Hash);
+ // Get the hash by bytes
+ string hash = HexTool.BytesToHexUnsafe(asset.Hash);
+ // Filter only current audio language file and other assets
+ if (FilterCurrentAudioLangFile(asset, voLangName, out bool IsHasHashMark))
+ {
+ // Convert and add the asset as FilePropertiesRemote to assetIndex
assetIndex.Add(new FilePropertiesRemote
{
N = asset.LocalName,
@@ -95,7 +116,7 @@ private void ConvertSRMetadataToAssetIndex(SRMetadataBase metadata, List 1, then start do filtering
if (nameDef.Length > 1)
{
- return (isHasHashMark = nameDef[0] == langName) || nameDef[0] == "SFX";
+ // Compare if the first name definition is equal to target langName.
+ // Also return if the file is an audio language file if it is a SFX file or not.
+ return nameDef[0] == langName || nameDef[0] == "SFX";
}
+ // If it's not in criteria of name definition, then return true as "normal asset"
return true;
default:
+ // return true as "normal asset"
return true;
}
}
diff --git a/CollapseLauncher/Classes/RepairManagement/StarRail/Repair.cs b/CollapseLauncher/Classes/RepairManagement/StarRail/Repair.cs
index 57b039d8d..7154029ad 100644
--- a/CollapseLauncher/Classes/RepairManagement/StarRail/Repair.cs
+++ b/CollapseLauncher/Classes/RepairManagement/StarRail/Repair.cs
@@ -76,9 +76,23 @@ private async Task RepairAssetTypeGeneric(FilePropertiesRemote asset, Http _http
string.Format(Lang._GameRepairPage.PerProgressSubtitle2, ConverterTool.SummarizeSizeSimple(_progressTotalSizeCurrent), ConverterTool.SummarizeSizeSimple(_progressTotalSize)),
true);
- // Start asset download task
- await RunDownloadTask(asset.S, asset.N, asset.RN, _httpClient, token);
- LogWriteLine($"File [T: {asset.FT}] {(asset.FT == FileType.Blocks ? asset.CRC : asset.N)} has been downloaded!", LogType.Default, true);
+ // If asset type is unused, then delete it
+ if (asset.FT == FileType.Unused)
+ {
+ FileInfo fileInfo = new FileInfo(asset.N);
+ if (fileInfo.Exists)
+ {
+ fileInfo.IsReadOnly = false;
+ fileInfo.Delete();
+ LogWriteLine($"File [T: {asset.FT}] {(asset.FT == FileType.Blocks ? asset.CRC : asset.N)} deleted!", LogType.Default, true);
+ }
+ }
+ else
+ {
+ // Start asset download task
+ await RunDownloadTask(asset.S, asset.N, asset.RN, _httpClient, token);
+ LogWriteLine($"File [T: {asset.FT}] {(asset.FT == FileType.Blocks ? asset.CRC : asset.N)} has been downloaded!", LogType.Default, true);
+ }
// Pop repair asset display entry
PopRepairAssetEntry();
diff --git a/CollapseLauncher/Classes/RepairManagement/StarRail/StarRailRepair.cs b/CollapseLauncher/Classes/RepairManagement/StarRail/StarRailRepair.cs
index 5f7eaa9f4..277962526 100644
--- a/CollapseLauncher/Classes/RepairManagement/StarRail/StarRailRepair.cs
+++ b/CollapseLauncher/Classes/RepairManagement/StarRail/StarRailRepair.cs
@@ -1,6 +1,5 @@
using CollapseLauncher.GameVersioning;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
using Hi3Helper.Data;
using Hi3Helper.Shared.ClassStruct;
using Microsoft.UI.Xaml;
@@ -14,15 +13,16 @@ internal partial class StarRailRepair :
ProgressBase, IRepair
{
#region Properties
- private GameTypeStarRailVersion _gameVersionManager { get => PageStatics._GameVersion as GameTypeStarRailVersion; }
+ private GameTypeStarRailVersion _innerGameVersionManager { get; set; }
private bool _isOnlyRecoverMain { get; set; }
#endregion
- public StarRailRepair(UIElement parentUI, bool onlyRecoverMainAsset = false, string versionOverride = null)
- : base(parentUI, null, "", versionOverride)
+ public StarRailRepair(UIElement parentUI, IGameVersionCheck GameVersionManager, bool onlyRecoverMainAsset = false, string versionOverride = null)
+ : base(parentUI, GameVersionManager, null, "", versionOverride)
{
// Get flag to only recover main assets
_isOnlyRecoverMain = onlyRecoverMainAsset;
+ _innerGameVersionManager = GameVersionManager as GameTypeStarRailVersion;
}
~StarRailRepair() => Dispose();
diff --git a/CollapseLauncher/CollapseLauncher.csproj b/CollapseLauncher/CollapseLauncher.csproj
index ecde80e64..274003dd8 100644
--- a/CollapseLauncher/CollapseLauncher.csproj
+++ b/CollapseLauncher/CollapseLauncher.csproj
@@ -9,7 +9,7 @@
preview
Debug;Release;Publish
true
- 1.71.2
+ 1.71.3
portable
app.manifest
CollapseLauncher.MainEntryPoint
@@ -20,10 +20,10 @@
true
true
true
+ true
DISABLE_XAML_GENERATED_MAIN;PREVIEW;DISABLETRANSPARENT;DISABLEMOVEMIGRATE
- False
DISABLE_XAML_GENERATED_MAIN;PREVIEW;DISABLETRANSPARENT;DISABLEMOVEMIGRATE
@@ -34,7 +34,7 @@
True
-
+
@@ -43,7 +43,7 @@
-
+
@@ -59,49 +59,81 @@
Always
+
Always
+
Always
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
+
+ Always
+
+
-
+
+
Always
-
+
+
Always
-
+
+
Always
-
+
+
Always
-
+
+
Always
-
+
+
Always
-
+
+
Always
+
Always
+
Always
+
Always
+
Always
+
Always
+
Always
diff --git a/CollapseLauncher/Properties/PublishProfiles/Publish-PreviewRelease.pubxml b/CollapseLauncher/Properties/PublishProfiles/Publish-PreviewRelease.pubxml
index 64d7f6c20..f6567951c 100644
--- a/CollapseLauncher/Properties/PublishProfiles/Publish-PreviewRelease.pubxml
+++ b/CollapseLauncher/Properties/PublishProfiles/Publish-PreviewRelease.pubxml
@@ -12,7 +12,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
win-x64
true
true
- false
+ true
true
partial
diff --git a/CollapseLauncher/Properties/PublishProfiles/Publish-StableRelease.pubxml b/CollapseLauncher/Properties/PublishProfiles/Publish-StableRelease.pubxml
index bb695f7ad..afaff8aa4 100644
--- a/CollapseLauncher/Properties/PublishProfiles/Publish-StableRelease.pubxml
+++ b/CollapseLauncher/Properties/PublishProfiles/Publish-StableRelease.pubxml
@@ -12,7 +12,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
win-x64
true
true
- false
+ true
true
partial
diff --git a/CollapseLauncher/XAMLs/Invoker/Classes/Migrate.cs b/CollapseLauncher/XAMLs/Invoker/Classes/Migrate.cs
index 6bb4172f8..0bc2d80ec 100644
--- a/CollapseLauncher/XAMLs/Invoker/Classes/Migrate.cs
+++ b/CollapseLauncher/XAMLs/Invoker/Classes/Migrate.cs
@@ -67,7 +67,7 @@ public void DoMigrationBHI3L(string version, string registryName, string sourceG
Registry.CurrentUser.OpenSubKey(@"Software\Bp\Better HI3 Launcher", true)
.SetValue(registryName,
- Encoding.UTF8.GetBytes(JsonSerializer.Serialize(info, typeof(BHI3LInfo), BHI3LInfoContext.Default)),
+ Encoding.UTF8.GetBytes(JsonSerializer.Serialize(info, typeof(BHI3LInfo), CoreLibraryJSONContext.Default)),
RegistryValueKind.Binary);
}
catch (Exception ex)
diff --git a/CollapseLauncher/XAMLs/MainApp/DisconnectedPage.xaml b/CollapseLauncher/XAMLs/MainApp/DisconnectedPage.xaml
index 46ba53d82..a1641f0ea 100644
--- a/CollapseLauncher/XAMLs/MainApp/DisconnectedPage.xaml
+++ b/CollapseLauncher/XAMLs/MainApp/DisconnectedPage.xaml
@@ -21,7 +21,7 @@
-
diff --git a/CollapseLauncher/XAMLs/MainApp/MainPage.xaml b/CollapseLauncher/XAMLs/MainApp/MainPage.xaml
index 9e3ab8525..22ccc43fe 100644
--- a/CollapseLauncher/XAMLs/MainApp/MainPage.xaml
+++ b/CollapseLauncher/XAMLs/MainApp/MainPage.xaml
@@ -15,140 +15,32 @@
-
-
+
+
+ Loaded="NavView_Loaded"
+ BackRequested="NavigationViewControl_BackRequested"
+ PaneOpening="NavigationPanelOpening_Event"
+ PaneClosing="NavigationPanelClosing_Event">
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -175,13 +67,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -193,7 +195,7 @@
-
+
diff --git a/CollapseLauncher/XAMLs/MainApp/MainPage.xaml.cs b/CollapseLauncher/XAMLs/MainApp/MainPage.xaml.cs
index 06bfd3c57..49f12c60d 100644
--- a/CollapseLauncher/XAMLs/MainApp/MainPage.xaml.cs
+++ b/CollapseLauncher/XAMLs/MainApp/MainPage.xaml.cs
@@ -21,6 +21,7 @@
using Windows.Foundation;
using Windows.Graphics;
using static CollapseLauncher.InnerLauncherConfig;
+using static CollapseLauncher.Statics.GamePropertyVault;
using static Hi3Helper.Locale;
using static Hi3Helper.Logger;
using static Hi3Helper.Preset.ConfigV2Store;
@@ -31,6 +32,7 @@ namespace CollapseLauncher
public partial class MainPage : Page
{
private bool LockRegionChangeBtn;
+ private bool IsLoadFrameCompleted = true;
public static bool IsChangeDragArea = true;
private RectInt32[] DragAreaMode_Normal
@@ -194,17 +196,21 @@ private void SubscribeEvents()
MainFrameChangerInvoker.FrameEvent += MainFrameChangerInvoker_FrameEvent;
NotificationInvoker.EventInvoker += NotificationInvoker_EventInvoker;
BackgroundImgChangerInvoker.ImgEvent += CustomBackgroundChanger_Event;
+ BackgroundImgChangerInvoker.IsImageHide += BackgroundImg_IsImageHideEvent;
SpawnWebView2Invoker.SpawnEvent += SpawnWebView2Invoker_SpawnEvent;
ShowLoadingPageInvoker.PageEvent += ShowLoadingPageInvoker_PageEvent;
ChangeTitleDragAreaInvoker.TitleBarEvent += ChangeTitleDragAreaInvoker_TitleBarEvent;
}
+ private void BackgroundImg_IsImageHideEvent(object sender, bool e) => HideBackgroundImage(e);
+
private void UnsubscribeEvents()
{
ErrorSenderInvoker.ExceptionEvent -= ErrorSenderInvoker_ExceptionEvent;
MainFrameChangerInvoker.FrameEvent -= MainFrameChangerInvoker_FrameEvent;
NotificationInvoker.EventInvoker -= NotificationInvoker_EventInvoker;
BackgroundImgChangerInvoker.ImgEvent -= CustomBackgroundChanger_Event;
+ BackgroundImgChangerInvoker.IsImageHide -= BackgroundImg_IsImageHideEvent;
SpawnWebView2Invoker.SpawnEvent -= SpawnWebView2Invoker_SpawnEvent;
ShowLoadingPageInvoker.PageEvent -= ShowLoadingPageInvoker_PageEvent;
ChangeTitleDragAreaInvoker.TitleBarEvent -= ChangeTitleDragAreaInvoker_TitleBarEvent;
@@ -225,7 +231,7 @@ private void ChangeTitleDragAreaInvoker_TitleBarEvent(object sender, ChangeTitle
private void ShowLoadingPageInvoker_PageEvent(object sender, ShowLoadingPageProperty e)
{
- HideBackgroundImage(!e.Hide);
+ BackgroundImgChanger.ToggleBackground(e.Hide);
HideLoadingPopup(e.Hide, e.Title, e.Subtitle);
}
@@ -280,7 +286,7 @@ private async void CheckRunningGameInstance()
{
while (true && !App.IsAppKilled)
{
- string execName = Path.GetFileNameWithoutExtension(PageStatics._GameVersion.GamePreset.GameExecutableName);
+ string execName = Path.GetFileNameWithoutExtension(CurrentGameProperty._GameVersion.GamePreset.GameExecutableName);
App.IsGameRunning = Process.GetProcessesByName(execName).Length != 0 && !App.IsAppKilled;
await Task.Delay(500);
}
@@ -288,6 +294,19 @@ private async void CheckRunningGameInstance()
private void NotificationInvoker_EventInvoker(object sender, NotificationInvokerProp e)
{
+ if (e.IsCustomNotif)
+ {
+ if (e.CustomNotifAction == NotificationCustomAction.Add)
+ {
+ SpawnNotificationoUI(e.Notification.MsgId, e.OtherContent as InfoBar);
+ }
+ else
+ {
+ RemoveNotificationUI(e.Notification.MsgId);
+ }
+ return;
+ }
+
SpawnNotificationPush(e.Notification.Title, e.Notification.Message, e.Notification.Severity,
e.Notification.MsgId, e.Notification.IsClosable ?? true, e.Notification.IsDisposable ?? true, e.CloseAction,
e.OtherContent, e.IsAppNotif, e.Notification.Show, e.Notification.IsForceShowNotificationPanel);
@@ -343,7 +362,7 @@ private async Task FetchNotificationFeed()
{
await FallbackCDNUtil.DownloadCDNFallbackContent(_http, fs, string.Format(AppNotifURLPrefix, IsPreview ? "preview" : "stable"), TokenSource.Token);
fs.Position = 0;
- NotificationData = (NotificationPush)JsonSerializer.Deserialize(fs, typeof(NotificationPush), NotificationPushContext.Default);
+ NotificationData = (NotificationPush)JsonSerializer.Deserialize(fs, typeof(NotificationPush), InternalAppJSONContext.Default);
IsLoadNotifComplete = true;
NotificationData.EliminatePushList();
@@ -539,8 +558,6 @@ private void SpawnNotificationPush(string Title, string Content, NotifSeverity S
DispatcherQueue.TryEnqueue(() =>
{
- Grid Container = new Grid();
-
StackPanel OtherContentContainer = new StackPanel
{
Orientation = Orientation.Vertical,
@@ -587,29 +604,8 @@ private void SpawnNotificationPush(string Title, string Content, NotifSeverity S
Notification.Tag = MsgId;
Notification.CloseButtonClick += CloseClickHandler;
- Notification.Loaded += (a, b) =>
- {
- NoNotificationIndicator.Opacity = NotificationContainer.Children.Count > 0 ? 0f : 1f;
- NewNotificationCountBadge.Visibility = Visibility.Visible;
- NewNotificationCountBadge.Value++;
- };
- Notification.Closed += (s, a) =>
- {
- s.Translation -= Shadow32;
- s.Height = 0;
- s.Margin = new Thickness(0);
- int msg = (int)s.Tag;
- if (NotificationData.CurrentShowMsgIds.Contains(msg))
- {
- NotificationData.CurrentShowMsgIds.Remove(msg);
- }
- NotificationContainer.Children.Remove(Container);
- NoNotificationIndicator.Opacity = NotificationContainer.Children.Count > 0 ? 0f : 1f;
- };
-
- Container.Children.Add(Notification);
- NotificationContainer.Children.Add(Container);
+ SpawnNotificationoUI(MsgId, Notification);
if (ForceShowNotificationPanel && !IsNotificationPanelShow)
{
@@ -618,6 +614,56 @@ private void SpawnNotificationPush(string Title, string Content, NotifSeverity S
});
}
+ private void SpawnNotificationoUI(int tagID, InfoBar Notification)
+ {
+ Grid Container = new Grid() { Tag = tagID, };
+ Notification.Loaded += (a, b) =>
+ {
+ NoNotificationIndicator.Opacity = NotificationContainer.Children.Count > 0 ? 0f : 1f;
+ NewNotificationCountBadge.Visibility = Visibility.Visible;
+ NewNotificationCountBadge.Value++;
+ };
+
+ Notification.Closed += (s, a) =>
+ {
+ s.Translation -= Shadow32;
+ s.Height = 0;
+ s.Margin = new Thickness(0);
+ int msg = (int)s.Tag;
+
+ if (NotificationData.CurrentShowMsgIds.Contains(msg))
+ {
+ NotificationData.CurrentShowMsgIds.Remove(msg);
+ }
+ NotificationContainer.Children.Remove(Container);
+ NoNotificationIndicator.Opacity = NotificationContainer.Children.Count > 0 ? 0f : 1f;
+
+ if (NewNotificationCountBadge.Value > 0)
+ {
+ NewNotificationCountBadge.Value--;
+ }
+ NoNotificationIndicator.Opacity = NotificationContainer.Children.Count > 0 ? 0f : 1f;
+ NewNotificationCountBadge.Visibility = NotificationContainer.Children.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
+ };
+
+ Container.Children.Add(Notification);
+ NotificationContainer.Children.Add(Container);
+ }
+
+ private void RemoveNotificationUI(int tagID)
+ {
+ Grid notif = NotificationContainer.Children.OfType().Where(x => (int)x.Tag == tagID).FirstOrDefault();
+ if (notif != null)
+ {
+ NotificationContainer.Children.Remove(notif);
+ InfoBar notifBar = notif.Children.OfType()?.FirstOrDefault();
+ if (notifBar != null)
+ {
+ notifBar.IsOpen = false;
+ }
+ }
+ }
+
private void NeverAskNotif_Checked(object sender, RoutedEventArgs e)
{
string[] Data = (sender as CheckBox).Tag.ToString().Split(',');
@@ -876,24 +922,24 @@ private void InitializeNavigationItems()
NavigationViewControl.MenuItems.Add(new NavigationViewItem()
{ Content = Lang._HomePage.PageTitle, Icon = IconLauncher, Tag = "launcher" });
- if ((PageStatics._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false) || (PageStatics._GameVersion.GamePreset.IsRepairEnabled ?? false))
+ if ((GetCurrentGameProperty()._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false) || (GetCurrentGameProperty()._GameVersion.GamePreset.IsRepairEnabled ?? false))
{
- NavigationViewControl.MenuItems.Add(new NavigationViewItemSeparator());
+ NavigationViewControl.MenuItems.Add(new NavigationViewItemHeader() { Content = "Utilities" });
- if (PageStatics._GameVersion.GamePreset.IsRepairEnabled ?? false)
+ if (GetCurrentGameProperty()._GameVersion.GamePreset.IsRepairEnabled ?? false)
{
NavigationViewControl.MenuItems.Add(new NavigationViewItem()
{ Content = Lang._GameRepairPage.PageTitle, Icon = IconRepair, Tag = "repair" });
}
- if (PageStatics._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false)
+ if (GetCurrentGameProperty()._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false)
{
NavigationViewControl.MenuItems.Add(new NavigationViewItem()
{ Content = Lang._CachesPage.PageTitle, Icon = IconCaches, Tag = "caches" });
}
}
- switch (PageStatics._GameVersion.GameType)
+ switch (GetCurrentGameProperty()._GameVersion.GameType)
{
case GameType.Honkai:
NavigationViewControl.MenuItems.Add(new NavigationViewItem()
@@ -905,7 +951,7 @@ private void InitializeNavigationItems()
break;
}
- if (PageStatics._GameVersion.GameType == GameType.Genshin)
+ if (GetCurrentGameProperty()._GameVersion.GameType == GameType.Genshin)
{
NavigationViewControl.MenuItems.Add(new NavigationViewItem()
{ Content = Lang._GenshinGameSettingsPage.PageTitle, Icon = IconGameSettings, Tag = "genshingamesettings" });
@@ -930,82 +976,57 @@ private void NavView_Loaded(object sender, RoutedEventArgs e)
private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
- if (args.IsSettingsInvoked)
- {
- MainFrameChanger.ChangeMainFrame(typeof(SettingsPage));
- PreviousTag = "settings";
- LogWriteLine($"Page changed to App Settings", LogType.Scheme);
- }
- else
+ if (!IsLoadFrameCompleted) return;
+ if (args.IsSettingsInvoked && PreviousTag != "settings") Navigate(typeof(SettingsPage), "settings");
+
+ NavigationViewItem item = sender.MenuItems.OfType().FirstOrDefault(x => (string)x.Content == (string)args.InvokedItem);
+ if (item == null) return;
+
+ string itemTag = (string)item.Tag;
+ if (itemTag == PreviousTag) return;
+
+ switch (itemTag)
{
- if (sender.MenuItems.Count != 0)
- {
- var item = sender.MenuItems.OfType().FirstOrDefault(x => (string)x.Content == (string)args.InvokedItem);
- NavView_Navigate(item);
- }
- else
- {
- MainFrameChanger.ChangeMainFrame(typeof(HomePage), new DrillInNavigationTransitionInfo());
- }
+ case "launcher":
+ Navigate(typeof(HomePage), itemTag);
+ break;
+
+ case "repair":
+ if (!(GetCurrentGameProperty()._GameVersion.GamePreset.IsRepairEnabled ?? false))
+ Navigate(typeof(UnavailablePage), itemTag);
+ else
+ Navigate(IsGameInstalled() ? typeof(RepairPage) : typeof(NotInstalledPage), itemTag);
+ break;
+
+ case "caches":
+ if (GetCurrentGameProperty()._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false)
+ Navigate(IsGameInstalled() ? typeof(CachesPage) : typeof(NotInstalledPage), itemTag);
+ else
+ Navigate(typeof(UnavailablePage), itemTag);
+ break;
+
+ case "gamesettings":
+ Navigate(IsGameInstalled() ? typeof(GameSettingsPage) : typeof(NotInstalledPage), itemTag);
+ break;
+
+ case "starrailgamesettings":
+ Navigate(IsGameInstalled() ? typeof(StarRailGameSettingsPage) : typeof(NotInstalledPage), itemTag);
+ break;
+
+ case "genshingamesettings":
+ Navigate(IsGameInstalled() ? typeof(GenshinGameSettingsPage) : typeof(NotInstalledPage), itemTag);
+ break;
}
}
- void Navigate(Type sourceType, bool hideImage, NavigationViewItem tag)
+ private List PreviousTagString = new List();
+
+ void Navigate(Type sourceType, string tagStr)
{
- string tagStr = (string)tag.Tag;
MainFrameChanger.ChangeMainFrame(sourceType, new DrillInNavigationTransitionInfo());
PreviousTag = tagStr;
- }
-
- private void NavView_Navigate(NavigationViewItem item)
- {
- try
- {
- if (!(PreviousTag == (string)item.Tag))
- {
- switch (item.Tag)
- {
- case "launcher":
- Navigate(typeof(HomePage), false, item);
- break;
-
- case "repair":
- if (!(PageStatics._GameVersion.GamePreset.IsRepairEnabled ?? false))
- Navigate(typeof(UnavailablePage), true, item);
- else
- Navigate(IsGameInstalled() ? typeof(RepairPage) : typeof(NotInstalledPage), true, item);
- break;
-
- case "caches":
- if (PageStatics._GameVersion.GamePreset.IsCacheUpdateEnabled ?? false)
- Navigate(IsGameInstalled() ? typeof(CachesPage) : typeof(NotInstalledPage), true, item);
- else
- Navigate(typeof(UnavailablePage), true, item);
- break;
-
- case "cutscenes":
- throw new NotImplementedException("Cutscenes Downloading Page isn't yet implemented for now.");
-
- case "gamesettings":
- Navigate(IsGameInstalled() ? typeof(GameSettingsPage) : typeof(NotInstalledPage), true, item);
- break;
-
- case "starrailgamesettings":
- Navigate(IsGameInstalled() ? typeof(StarRailGameSettingsPage) : typeof(NotInstalledPage), true, item);
- break;
-
- case "genshingamesettings":
- Navigate(IsGameInstalled() ? typeof(GenshinGameSettingsPage) : typeof(NotInstalledPage), true, item);
- break;
- }
- LogWriteLine($"Page changed to {item.Content}", LogType.Scheme);
- }
- }
- catch (Exception ex)
- {
- LogWriteLine($"{ex}", LogType.Error, true);
- ErrorSender.SendException(ex);
- }
+ PreviousTagString.Add(tagStr);
+ LogWriteLine($"Page changed to {sourceType.Name} with Tag: {tagStr}", LogType.Scheme);
}
private bool IsGameInstalled() => GameInstallationState == GameInstallStateEnum.Installed ||
@@ -1034,13 +1055,11 @@ private void ErrorSenderInvoker_ExceptionEvent(object sender, ErrorProperties e)
if (e.Exception.GetType() == typeof(NotImplementedException))
{
PreviousTag = "unavailable";
- HideBackgroundImage();
MainFrameChanger.ChangeMainFrame(typeof(UnavailablePage));
}
else
{
PreviousTag = "crashinfo";
- HideBackgroundImage();
MainFrameChanger.ChangeMainFrame(typeof(UnhandledExceptionPage));
}
});
@@ -1048,30 +1067,10 @@ private void ErrorSenderInvoker_ExceptionEvent(object sender, ErrorProperties e)
private void MainFrameChangerInvoker_FrameEvent(object sender, MainFrameProperties e)
{
- switch (e.FrameTo.Name)
- {
- case "HomePage":
- HideBackgroundImage(false);
- LauncherFrame.Navigate(e.FrameTo, null, e.Transition);
- break;
- case "RepairPage":
- PreviousTag = "repair";
- IList menuItems = NavigationViewControl.MenuItems;
- if (menuItems != null && menuItems.Count > 2)
- {
- NavigationViewControl.SelectedItem = (NavigationViewItem)menuItems[2];
- }
- HideBackgroundImage();
- LauncherFrame.Navigate(e.FrameTo, null, e.Transition);
- break;
- default:
- case "UnhandledExceptionPage":
- case "BlankPage":
- HideBackgroundImage();
- LauncherFrame.Navigate(e.FrameTo, null, e.Transition);
- break;
- }
+ IsLoadFrameCompleted = false;
m_appCurrentFrameName = e.FrameTo.Name;
+ LauncherFrame.Navigate(e.FrameTo, null, e.Transition);
+ IsLoadFrameCompleted = true;
}
private void SpawnWebView2Panel(Uri URL)
@@ -1145,5 +1144,114 @@ private void NotificationContainerBackground_PointerPressed(object sender, Micro
ToggleNotificationPanelBtn.IsChecked = false;
ShowHideNotificationPanel();
}
+
+ private void NavigationViewControl_BackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
+ {
+ if (LauncherFrame.CanGoBack && IsLoadFrameCompleted)
+ {
+ LauncherFrame.GoBack();
+ if (PreviousTagString.Count < 1) return;
+
+ string lastPreviousTag = PreviousTagString[PreviousTagString.Count - 1];
+ string currentNavigationItemTag = (string)((NavigationViewItem)sender.SelectedItem).Tag;
+
+ if (lastPreviousTag.ToLower() == currentNavigationItemTag.ToLower())
+ {
+ string goLastPreviousTag = PreviousTagString[PreviousTagString.Count - 2];
+ NavigationViewItem goPreviousNavigationItem = sender.MenuItems.OfType().Where(x => goLastPreviousTag == (string)x.Tag).FirstOrDefault();
+
+ if (goLastPreviousTag == "settings")
+ {
+ PreviousTag = goLastPreviousTag;
+ PreviousTagString.RemoveAt(PreviousTagString.Count - 1);
+ sender.SelectedItem = sender.SettingsItem;
+ return;
+ }
+
+ if (goPreviousNavigationItem != null)
+ {
+ PreviousTag = goLastPreviousTag;
+ PreviousTagString.RemoveAt(PreviousTagString.Count - 1);
+ sender.SelectedItem = goPreviousNavigationItem;
+ }
+ }
+ }
+ }
+
+ private bool IsTitleIconForceShow = false;
+
+ private void NavigationPanelOpening_Event(NavigationView sender, object args)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 48;
+ GridBG_Icon.Margin = curMargin;
+ IsTitleIconForceShow = true;
+ ToggleTitleIcon(false);
+ }
+
+ private void NavigationPanelClosing_Event(NavigationView sender, NavigationViewPaneClosingEventArgs args)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 58;
+ GridBG_Icon.Margin = curMargin;
+ IsTitleIconForceShow = false;
+ ToggleTitleIcon(true);
+ }
+
+ private void ToggleTitleIcon(bool hide)
+ {
+ if (!hide)
+ {
+ GridBG_IconTitle.Width = double.NaN;
+ if (PreviewBuildIndicator.Visibility == Visibility.Collapsed)
+ GridBG_IconTitle.Visibility = Visibility.Visible;
+ return;
+ }
+
+ GridBG_IconTitle.Width = 0;
+ if (PreviewBuildIndicator.Visibility == Visibility.Collapsed)
+ GridBG_IconTitle.Visibility = Visibility.Collapsed;
+ }
+
+ private void GridBG_Icon_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
+ {
+ if (!IsTitleIconForceShow)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 50;
+ GridBG_Icon.Margin = curMargin;
+ ToggleTitleIcon(false);
+ }
+ }
+
+ private void GridBG_Icon_PointerExited(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
+ {
+ if (!IsTitleIconForceShow)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 58;
+ GridBG_Icon.Margin = curMargin;
+ ToggleTitleIcon(true);
+ }
+ }
+
+ private void GridBG_Icon_Click(object sender, RoutedEventArgs e)
+ {
+ if (PreviousTag.ToLower() == "launcher") return;
+
+ MainFrameChanger.ChangeMainFrame(typeof(HomePage));
+ PreviousTag = "launcher";
+ PreviousTagString.Add(PreviousTag);
+
+ NavigationViewItem navItem = NavigationViewControl.MenuItems
+ .OfType()
+ .Where(x => ((string)x.Tag).ToLower() == PreviousTag)
+ .FirstOrDefault();
+
+ if (navItem != null)
+ {
+ NavigationViewControl.SelectedItem = navItem;
+ }
+ }
}
}
diff --git a/CollapseLauncher/XAMLs/MainApp/MainWindow.xaml.cs b/CollapseLauncher/XAMLs/MainApp/MainWindow.xaml.cs
index 251f8607e..bf099aa70 100644
--- a/CollapseLauncher/XAMLs/MainApp/MainWindow.xaml.cs
+++ b/CollapseLauncher/XAMLs/MainApp/MainWindow.xaml.cs
@@ -37,7 +37,7 @@ public void InitializeWindowProperties()
try
{
InitializeWindowSettings();
- m_appWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
+ if (m_appWindow.TitleBar.ExtendsContentIntoTitleBar) m_appWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
if (IsFirstInstall)
{
@@ -68,6 +68,7 @@ public void StartMainPage()
{
SetWindowSize(m_windowHandle, WindowSize.WindowSize.CurrentWindowSize.WindowBounds.Width, WindowSize.WindowSize.CurrentWindowSize.WindowBounds.Height);
rootFrame.Navigate(typeof(MainPage), null, new DrillInNavigationTransitionInfo());
+ // rootFrame.Navigate(typeof(MainPageNew), null, new DrillInNavigationTransitionInfo());
}
private void InitializeAppWindowAndIntPtr()
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml b/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml
index cd02529d0..baf8caae7 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml
@@ -11,7 +11,7 @@
mc:Ignorable="d"
Loaded="InitializeLoaded" Unloaded="Page_Unloaded">
-
+
@@ -32,7 +32,7 @@
IsReadOnly="True"
AutoGenerateColumns="False"
CanUserSortColumns="True"
- ItemsSource="{x:Bind statics:PageStatics._GameCache.AssetEntry}">
+ ItemsSource="{x:Bind CurrentGameProperty._GameCache.AssetEntry}">
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml.cs b/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml.cs
index df18935c4..832854f35 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/CachesPage.xaml.cs
@@ -1,4 +1,5 @@
-using Hi3Helper;
+using CollapseLauncher.Statics;
+using Hi3Helper;
#if !DISABLEDISCORD
using Hi3Helper.DiscordPresence;
#endif
@@ -9,7 +10,6 @@
using System;
using System.Threading.Tasks;
using static CollapseLauncher.InnerLauncherConfig;
-using static CollapseLauncher.Statics.PageStatics;
using static Hi3Helper.Locale;
using static Hi3Helper.Logger;
using static Hi3Helper.Shared.Region.LauncherConfig;
@@ -18,9 +18,14 @@ namespace CollapseLauncher.Pages
{
public sealed partial class CachesPage : Page
{
+ private GamePresetProperty CurrentGameProperty { get; set; }
+
public CachesPage()
{
+ CurrentGameProperty = GamePropertyVault.GetCurrentGameProperty();
+
this.InitializeComponent();
+ BackgroundImgChanger.ToggleBackground(true);
#if !DISABLEDISCORD
AppDiscordPresence.SetActivity(ActivityType.Cache);
#endif
@@ -57,7 +62,7 @@ public async void RunCheckRoutine(object sender, bool isFast, bool isMainButton)
{
AddEvent();
- bool IsNeedUpdate = await _GameCache.StartCheckRoutine(isFast);
+ bool IsNeedUpdate = await CurrentGameProperty._GameCache.StartCheckRoutine(isFast);
UpdateCachesBtn.IsEnabled = IsNeedUpdate;
CheckUpdateBtn.IsEnabled = !IsNeedUpdate;
@@ -94,7 +99,7 @@ public async void StartCachesUpdate(object sender, RoutedEventArgs e)
{
AddEvent();
- await _GameCache.StartUpdateRoutine();
+ await CurrentGameProperty._GameCache.StartUpdateRoutine();
UpdateCachesBtn.IsEnabled = false;
CheckUpdateBtn.IsEnabled = true;
@@ -135,16 +140,16 @@ private void SetMainCheckUpdateBtnProperty(object sender)
private void AddEvent()
{
- _GameCache.ProgressChanged += _cacheTool_ProgressChanged;
- _GameCache.StatusChanged += _cacheTool_StatusChanged;
+ CurrentGameProperty._GameCache.ProgressChanged += _cacheTool_ProgressChanged;
+ CurrentGameProperty._GameCache.StatusChanged += _cacheTool_StatusChanged;
CachesTotalProgressBar.IsIndeterminate = true;
}
private void RemoveEvent()
{
- _GameCache.ProgressChanged -= _cacheTool_ProgressChanged;
- _GameCache.StatusChanged -= _cacheTool_StatusChanged;
+ CurrentGameProperty._GameCache.ProgressChanged -= _cacheTool_ProgressChanged;
+ CurrentGameProperty._GameCache.StatusChanged -= _cacheTool_StatusChanged;
CachesTotalProgressBar.IsIndeterminate = false;
}
@@ -188,7 +193,7 @@ private void ResetStatusAndButtonState()
public void CancelOperation(object sender, RoutedEventArgs e)
{
- _GameCache?.CancelRoutine();
+ CurrentGameProperty._GameCache?.CancelRoutine();
}
private void InitializeLoaded(object sender, RoutedEventArgs e)
@@ -215,7 +220,7 @@ private void InitializeLoaded(object sender, RoutedEventArgs e)
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
- _GameCache?.CancelRoutine();
+ CurrentGameProperty._GameCache?.CancelRoutine();
}
}
}
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/InstallationConvert.xaml.cs b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/InstallationConvert.xaml.cs
index b02a6b6f2..1b13c6a79 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/InstallationConvert.xaml.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/InstallationConvert.xaml.cs
@@ -34,11 +34,13 @@ public partial class InstallationConvert : Page
IniFile SourceIniFile;
CancellationTokenSource tokenSource = new CancellationTokenSource();
Dictionary ConvertibleRegions;
+ private GamePresetProperty CurrentGameProperty { get; set; }
public InstallationConvert()
{
try
{
+ CurrentGameProperty = GamePropertyVault.GetCurrentGameProperty();
this.InitializeComponent();
}
catch (Exception ex)
@@ -107,12 +109,12 @@ public async void StartConversionProcess()
}
catch (TaskCanceledException)
{
- LogWriteLine($"Conversion process is cancelled for Game {PageStatics._GameVersion.GamePreset.ZoneFullname}");
+ LogWriteLine($"Conversion process is cancelled for Game {CurrentGameProperty._GameVersion.GamePreset.ZoneFullname}");
OperationCancelled();
}
catch (OperationCanceledException)
{
- LogWriteLine($"Conversion process is cancelled for Game {PageStatics._GameVersion.GamePreset.ZoneFullname}");
+ LogWriteLine($"Conversion process is cancelled for Game {CurrentGameProperty._GameVersion.GamePreset.ZoneFullname}");
OperationCancelled();
}
catch (Exception ex)
@@ -157,7 +159,7 @@ private async Task FetchDataIntegrityURL(PresetConfigV2 Profile)
string repoListURL = string.Format(AppGameRepoIndexURLPrefix, Profile.ProfileName);
await FallbackCDNUtil.DownloadCDNFallbackContent(_Http, s, repoListURL, tokenSource.Token);
s.Position = 0;
- _RepoList = (Dictionary)JsonSerializer.Deserialize(s, typeof(Dictionary), D_StringString.Default);
+ _RepoList = (Dictionary)JsonSerializer.Deserialize(s, typeof(Dictionary), CoreLibraryJSONContext.Default);
}
}
finally
@@ -171,7 +173,7 @@ private async Task FetchDataIntegrityURL(PresetConfigV2 Profile)
{
await _Http.Download(Profile.LauncherResourceURL, s, null, null, tokenSource.Token);
s.Position = 0;
- _Entry = (RegionResourceProp)JsonSerializer.Deserialize(s, typeof(RegionResourceProp), RegionResourcePropContext.Default);
+ _Entry = (RegionResourceProp)JsonSerializer.Deserialize(s, typeof(RegionResourceProp), CoreLibraryJSONContext.Default);
}
GameVersion = _Entry.data.game.latest.version;
@@ -195,6 +197,32 @@ public bool IsSourceGameExist(PresetConfigV2 Profile)
if (!Directory.Exists(GamePath))
return false;
+ // Concat the vendor app info file and return if it doesn't exist
+ string infoVendorPath = Path.Combine(GamePath, $"{Path.GetFileNameWithoutExtension(Profile.GameExecutableName)}_Data\\app.info");
+ if (!File.Exists(infoVendorPath)) return false;
+
+ // If does, then process the file
+ string[] infoEntries = File.ReadAllLines(infoVendorPath);
+ if (infoEntries.Length < 2) return false;
+
+ // Try parse the vendor name and internal game name. If parsing fail, then return false
+ if (!Enum.TryParse(infoEntries[0], out GameVendorType _VendorType)) return false;
+ if (!(_VendorType == SourceProfile.VendorType && infoEntries[1] == SourceProfile.InternalGameNameInConfig)) return false;
+
+ // Try load the Version INI file
+ string SourceINIVersionPath = Path.Combine(GamePath, "config.ini");
+ if (!File.Exists(SourceINIVersionPath)) return false;
+ IniFile SourceIniVersionFile = new IniFile();
+ SourceIniVersionFile.Load(SourceINIVersionPath);
+
+ // Check if the version value exist and matches
+ if (!(SourceIniVersionFile.ContainsSection("General") && SourceIniVersionFile["General"].ContainsKey("game_version"))) return false;
+ string localVersionString = SourceIniVersionFile["General"]["game_version"].ToString();
+ if (string.IsNullOrEmpty(localVersionString)) return false;
+ GameVersion localVersion = new GameVersion(localVersionString);
+ GameVersion remoteVersion = CurrentGameProperty._GameVersion.GetGameVersionAPI();
+ if (!localVersion.IsMatch(remoteVersion)) return false;
+
ExecPath = Path.Combine(GamePath, Profile.GameExecutableName);
if (!File.Exists(ExecPath))
return false;
@@ -322,7 +350,7 @@ private async Task DoDownloadRecipe()
string cPath = null;
while (!IsChoosen)
{
- string FileName = string.Format("Cookbook_{0}_{1}_{2}_lzma2_crc32.diff", SourceProfile.ProfileName, TargetProfile.ProfileName, GameVersion);
+ string FileName = string.Format("Cookbook_{0}_{1}_{2}_*_crc32.diff", SourceProfile.ProfileName, TargetProfile.ProfileName, GameVersion);
switch (await Dialog_LocateDownloadedConvertRecipe(Content, FileName))
{
case ContentDialogResult.Primary:
@@ -468,8 +496,9 @@ private void Step5ProgressEvents(object sender, ConvertProgress e)
public void ApplyConfiguration()
{
- PageStatics._GameVersion.GamePreset = TargetProfile;
- PageStatics._GameVersion.UpdateGamePath(Path.GetFileNameWithoutExtension(TargetProfile.ActualGameDataLocation));
+ CurrentGameProperty._GameVersion.GamePreset = TargetProfile;
+ CurrentGameProperty._GameVersion.Reinitialize();
+ CurrentGameProperty._GameVersion.UpdateGamePath(TargetProfile.ActualGameDataLocation);
string GameCategory = GetAppConfigValue("GameCategory").ToString();
SetPreviousGameRegion(GameCategory, TargetProfile.ZoneName);
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/SimpleDialogs.cs b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/SimpleDialogs.cs
index 7482c22df..8be65f6a7 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/SimpleDialogs.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/SimpleDialogs.cs
@@ -1,4 +1,4 @@
-using CollapseLauncher.Statics;
+using static CollapseLauncher.Statics.GamePropertyVault;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
@@ -170,10 +170,10 @@ public static async Task Dialog_ChangeReleaseChannel(string
);
}
- public static async Task Dialog_ExistingInstallation(UIElement Content) =>
+ public static async Task Dialog_ExistingInstallation(UIElement Content, string actualLocation) =>
await SpawnDialog(
Lang._Dialogs.ExistingInstallTitle,
- string.Format(Lang._Dialogs.ExistingInstallSubtitle, PageStatics._GameVersion.GamePreset.ActualGameDataLocation),
+ string.Format(Lang._Dialogs.ExistingInstallSubtitle, actualLocation),
Content,
Lang._Misc.Cancel,
Lang._Misc.YesMigrateIt,
@@ -250,6 +250,17 @@ await SpawnDialog(
Lang._StartupPage.ChooseFolderDialogSecondary
);
+ public static async Task Dialog_CannotUseAppLocationForGameDir(UIElement Content) =>
+ await SpawnDialog(
+ Lang._Dialogs.CannotUseAppLocationForGameDirTitle,
+ Lang._Dialogs.CannotUseAppLocationForGameDirSubtitle,
+ Content,
+ Lang._Misc.Okay,
+ null,
+ null,
+ ContentDialogButton.Close
+ );
+
public static async Task Dialog_ExistingDownload(UIElement Content, long partialLength, long contentLength) =>
await SpawnDialog(
Lang._Dialogs.InstallDataDownloadResumeTitle,
@@ -326,6 +337,16 @@ await SpawnDialog(
Lang._Misc.Yes,
null
);
+
+ public static async Task Dialog_StopGame(UIElement Content) =>
+ await SpawnDialog(
+ Lang._Dialogs.StopGameTitle,
+ Lang._Dialogs.StopGameSubtitle,
+ Content,
+ Lang._Misc.NoCancel,
+ Lang._Misc.Yes,
+ null
+ );
public static async Task Dialog_ResetPlaytime (UIElement Content)
{
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.Ext.cs b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.Ext.cs
index d743a3c0a..9934ad78b 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.Ext.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.Ext.cs
@@ -100,6 +100,12 @@ public bool IsFullscreenEnabled
}
}
+ public bool IsBorderlessEnabled
+ {
+ get => Settings.SettingsCollapseScreen.UseBorderlessScreen;
+ set => Settings.SettingsCollapseScreen.UseBorderlessScreen = value;
+ }
+
public bool IsCustomResolutionEnabled
{
get => Settings.SettingsCollapseScreen.UseCustomResolution;
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml
index 81ba6ba56..3cc68f3e3 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml
@@ -17,7 +17,7 @@
-
+
@@ -32,6 +32,9 @@
+
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml.cs b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml.cs
index b009c48db..0f16d9ed0 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/GameSettingsPage.xaml.cs
@@ -1,6 +1,5 @@
using CollapseLauncher.GameSettings.Honkai;
using CollapseLauncher.Interfaces;
-using CollapseLauncher.Statics;
#if !DISABLEDISCORD
using Hi3Helper.DiscordPresence;
#endif
@@ -16,24 +15,27 @@
using static Hi3Helper.Locale;
using static Hi3Helper.Logger;
using static Hi3Helper.Shared.Region.LauncherConfig;
-using static CollapseLauncher.GameSettings.Statics;
+using static CollapseLauncher.Statics.GamePropertyVault;
using Hi3Helper;
+using CollapseLauncher.Statics;
namespace CollapseLauncher.Pages
{
public partial class GameSettingsPage : Page
{
- private HonkaiSettings Settings { get => (HonkaiSettings)PageStatics._GameSettings; }
+ private GamePresetProperty CurrentGameProperty { get; set; }
+ private HonkaiSettings Settings { get => (HonkaiSettings)CurrentGameProperty._GameSettings; }
private Brush InheritApplyTextColor { get; set; }
private RegistryMonitor RegistryWatcher { get; set; }
private bool IsNoReload = false;
public GameSettingsPage()
{
+ CurrentGameProperty = GetCurrentGameProperty();
try
{
DispatcherQueue.TryEnqueue(() =>
{
- RegistryWatcher = new RegistryMonitor(RegistryHive.CurrentUser, Path.Combine(RegistryRootPath, PageStatics._GameVersion.GamePreset.InternalGameNameInConfig));
+ RegistryWatcher = new RegistryMonitor(RegistryHive.CurrentUser, Path.Combine($"Software\\{CurrentGameProperty._GameVersion.VendorTypeProp.VendorType}", CurrentGameProperty._GameVersion.GamePreset.InternalGameNameInConfig));
RegistryWatcher.Start();
ToggleRegistrySubscribe(true);
});
@@ -59,13 +61,14 @@ private void RegistryListener(object sender, EventArgs e)
{
if (!IsNoReload)
{
- LogWriteLine("Module: RegistryMonitor has detected registry change outside of the launcher! Reloading the page...", LogType.Warning, true);
+ LogWriteLine("[HI3 GSP Module] RegistryMonitor has detected registry change outside of the launcher! Reloading the page...", LogType.Warning, true);
DispatcherQueue.TryEnqueue(MainFrameChanger.ReloadCurrentMainFrame);
}
}
private void LoadPage()
{
+ BackgroundImgChanger.ToggleBackground(true);
Settings.ReloadSettings();
this.InitializeComponent();
@@ -189,11 +192,11 @@ private void ApplyButton_Click(object sender, RoutedEventArgs e)
public string CustomArgsValue
{
- get => ((IGameSettingsUniversal)PageStatics._GameSettings).SettingsCustomArgument.CustomArgumentValue;
+ get => ((IGameSettingsUniversal)CurrentGameProperty._GameSettings).SettingsCustomArgument.CustomArgumentValue;
set
{
ToggleRegistrySubscribe(false);
- ((IGameSettingsUniversal)PageStatics._GameSettings).SettingsCustomArgument.CustomArgumentValue = value;
+ ((IGameSettingsUniversal)CurrentGameProperty._GameSettings).SettingsCustomArgument.CustomArgumentValue = value;
ToggleRegistrySubscribe(true);
}
}
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.Ext.cs b/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.Ext.cs
index 052f12b80..7d8c5ba64 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.Ext.cs
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.Ext.cs
@@ -25,6 +25,12 @@ public bool IsFullscreenEnabled
}
}
+ public bool IsBorderlessEnabled
+ {
+ get => Settings.SettingsCollapseScreen.UseBorderlessScreen;
+ set => Settings.SettingsCollapseScreen.UseBorderlessScreen = value;
+ }
+
public bool IsCustomResolutionEnabled
{
get => Settings.SettingsCollapseScreen.UseCustomResolution;
diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.xaml b/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.xaml
index f9c3e96f9..6de0443ad 100644
--- a/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.xaml
+++ b/CollapseLauncher/XAMLs/MainApp/Pages/GenshinGameSettingsPage.xaml
@@ -21,7 +21,7 @@
-
+
@@ -32,11 +32,14 @@
-
+
+ HorizontalAlignment="Left" VerticalAlignment="Center"
+ IsChecked="{x:Bind IsFullscreenEnabled, Mode=TwoWay}" Margin="0,0,0,0"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CollapseLauncher/XAMLs/Prototype/MainPageNew.xaml.cs b/CollapseLauncher/XAMLs/Prototype/MainPageNew.xaml.cs
new file mode 100644
index 000000000..3ec8538be
--- /dev/null
+++ b/CollapseLauncher/XAMLs/Prototype/MainPageNew.xaml.cs
@@ -0,0 +1,48 @@
+using Hi3Helper;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System;
+using static Hi3Helper.Logger;
+
+namespace CollapseLauncher.Prototype
+{
+ public partial class MainPageNew : Page
+ {
+ public MainPageNew()
+ {
+ try
+ {
+ InitializeComponent();
+ }
+ catch (Exception ex)
+ {
+ LogWriteLine($"FATAL CRASH!!!\r\n{ex}", LogType.Error, true);
+ ErrorSender.SendException(ex);
+ }
+ }
+
+ private void nvSample_PaneOpening(NavigationView sender, object args)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 48;
+ GridBG_Icon.Margin = curMargin;
+ GridBG_IconTitle.Width = double.NaN;
+ if (PreviewBuildIndicator.Visibility == Visibility.Collapsed)
+ GridBG_IconTitle.Visibility = Visibility.Visible;
+ }
+
+ private void nvSample_PaneClosing(NavigationView sender, NavigationViewPaneClosingEventArgs args)
+ {
+ Thickness curMargin = GridBG_Icon.Margin;
+ curMargin.Left = 58;
+ GridBG_IconTitle.Width = 0;
+ GridBG_Icon.Margin = curMargin;
+ if (PreviewBuildIndicator.Visibility == Visibility.Collapsed)
+ GridBG_IconTitle.Visibility = Visibility.Collapsed;
+ }
+
+ private void NotificationContainerBackground_PointerPressed(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
+ {
+ }
+ }
+}
diff --git a/CollapseLauncher/XAMLs/Prototype/genshin-logo.png b/CollapseLauncher/XAMLs/Prototype/genshin-logo.png
new file mode 100644
index 000000000..5f76fde44
Binary files /dev/null and b/CollapseLauncher/XAMLs/Prototype/genshin-logo.png differ
diff --git a/CollapseLauncher/XAMLs/Prototype/honkai-logo.png b/CollapseLauncher/XAMLs/Prototype/honkai-logo.png
new file mode 100644
index 000000000..091171e20
Binary files /dev/null and b/CollapseLauncher/XAMLs/Prototype/honkai-logo.png differ
diff --git a/CollapseLauncher/XAMLs/Prototype/starrail-logo.png b/CollapseLauncher/XAMLs/Prototype/starrail-logo.png
new file mode 100644
index 000000000..f0b83e4c1
Binary files /dev/null and b/CollapseLauncher/XAMLs/Prototype/starrail-logo.png differ
diff --git a/CollapseLauncher/XAMLs/Prototype/zenless-logo.png b/CollapseLauncher/XAMLs/Prototype/zenless-logo.png
new file mode 100644
index 000000000..3a47b320d
Binary files /dev/null and b/CollapseLauncher/XAMLs/Prototype/zenless-logo.png differ
diff --git a/CollapseLauncher/XAMLs/StartUp/StartupLanguageSelect.xaml b/CollapseLauncher/XAMLs/StartUp/StartupLanguageSelect.xaml
index 8fe6e76b1..3b41d9b8f 100644
--- a/CollapseLauncher/XAMLs/StartUp/StartupLanguageSelect.xaml
+++ b/CollapseLauncher/XAMLs/StartUp/StartupLanguageSelect.xaml
@@ -17,7 +17,7 @@
-
+
diff --git a/CollapseLauncher/XAMLs/Updater/Classes/Updater.cs b/CollapseLauncher/XAMLs/Updater/Classes/Updater.cs
index e0fbc3c08..1d098193c 100644
--- a/CollapseLauncher/XAMLs/Updater/Classes/Updater.cs
+++ b/CollapseLauncher/XAMLs/Updater/Classes/Updater.cs
@@ -132,7 +132,7 @@ private async Task StartLegacyUpdate()
{
await FallbackCDNUtil.DownloadCDNFallbackContent(_httpClient, ms, $"{this.ChannelName.ToLower()}/fileindex.json", default);
ms.Position = 0;
- AppUpdateVersionProp updateInfo = (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), AppUpdateVersionPropContext.Default);
+ AppUpdateVersionProp updateInfo = (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), InternalAppJSONContext.Default);
NewVersionTag = new GameVersion(updateInfo.ver);
UpdateStatus();
UpdateProgress();
diff --git a/CollapseLauncher/XAMLs/Updater/UpdaterWindow.xaml.cs b/CollapseLauncher/XAMLs/Updater/UpdaterWindow.xaml.cs
index 71b0a1aa0..e41c204b1 100644
--- a/CollapseLauncher/XAMLs/Updater/UpdaterWindow.xaml.cs
+++ b/CollapseLauncher/XAMLs/Updater/UpdaterWindow.xaml.cs
@@ -63,7 +63,7 @@ private async void StartAsyncRoutine()
{
await FallbackCDNUtil.DownloadCDNFallbackContent(_httpClient, ms, $"{m_arguments.Updater.UpdateChannel.ToString().ToLower()}/fileindex.json", default);
ms.Position = 0;
- updateInfo = (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), AppUpdateVersionPropContext.Default);
+ updateInfo = (AppUpdateVersionProp)JsonSerializer.Deserialize(ms, typeof(AppUpdateVersionProp), InternalAppJSONContext.Default);
NewVersionLabel.Text = new GameVersion(updateInfo.ver).VersionString;
}
diff --git a/CollapseLauncher/packages.lock.json b/CollapseLauncher/packages.lock.json
new file mode 100644
index 000000000..f5c141836
--- /dev/null
+++ b/CollapseLauncher/packages.lock.json
@@ -0,0 +1,2259 @@
+{
+ "version": 1,
+ "dependencies": {
+ "net7.0-windows10.0.19041": {
+ "Clowd.Squirrel": {
+ "type": "Direct",
+ "requested": "[2.9.42, )",
+ "resolved": "2.9.42",
+ "contentHash": "bM7h3tqoenZD+tmiV7pUnFdJ/o1oOrC21PaS8crMDRDOuGB4YqsgzlUKFD1g8X6z64IRBqzlUwEKzpsFyFc0mQ==",
+ "dependencies": {
+ "SharpCompress": "0.31.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI": {
+ "type": "Direct",
+ "requested": "[7.1.2, )",
+ "resolved": "7.1.2",
+ "contentHash": "jF1GdEJsZX5o81ZfLjSjgC5RuYwQneuW2mdFIb7FDFzITsgqCn7mfn7BglpNiXvjExkocmAKbBgmCcbp0Nypmw==",
+ "dependencies": {
+ "CommunityToolkit.WinUI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls": {
+ "type": "Direct",
+ "requested": "[7.1.2, )",
+ "resolved": "7.1.2",
+ "contentHash": "+aDc1KqmlYM+HE0Mw5OnfQBOFhY0c7zp1aGz/4qs+1I+Xk8Ot3IRwvs8dYxBEGCD9YzE2OzaJLPztBpQ9JEWig==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI.Controls.Core": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.DataGrid": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Input": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Layout": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Markdown": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Media": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "Microsoft.Windows.CsWinRT": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "viZIwWVUBp7x9QprOZbvocWasVIAfaXN2BK7tgMijYKe4X+WuU1m4RdqE8P2wv+o3q0Bk8mWsUFaMm36rsCvNg=="
+ },
+ "Microsoft.Windows.SDK.BuildTools": {
+ "type": "Direct",
+ "requested": "[10.0.22621.756, )",
+ "resolved": "10.0.22621.756",
+ "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA=="
+ },
+ "Microsoft.WindowsAppSDK": {
+ "type": "Direct",
+ "requested": "[1.3.230724000, )",
+ "resolved": "1.3.230724000",
+ "contentHash": "cCw26h8Uh8IjDMOUzHaR7/IKxEVJxuqEOgBlmLj0Pu1wDezZb9J0Wz53Vop10FQUOZaTfnwDcHavyPTxgkwbKQ==",
+ "dependencies": {
+ "Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
+ }
+ },
+ "System.CommandLine": {
+ "type": "Direct",
+ "requested": "[2.0.0-beta3.22114.1, )",
+ "resolved": "2.0.0-beta3.22114.1",
+ "contentHash": "QMzk1jj+PzdGbwuVsxII7FcQaCelnK+TcRcAqOGVoPovLBCSQPdikKiEzb56vAidvum5t4LSdDZ34O4j7+ALgw=="
+ },
+ "System.Drawing.Common": {
+ "type": "Direct",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
+ "dependencies": {
+ "Microsoft.Win32.SystemEvents": "7.0.0"
+ }
+ },
+ "ColorCode.Core": {
+ "type": "Transitive",
+ "resolved": "2.0.13",
+ "contentHash": "v0xqipj/6h2TpIKSrOCZpXMmOGvLsyO2prWBXY6t+lduexDSimqKIZXTTZkpq/vG2kNxB8K8nzyrkIB3usoN7A==",
+ "dependencies": {
+ "NETStandard.Library": "1.6.1"
+ }
+ },
+ "ColorCode.WinUI": {
+ "type": "Transitive",
+ "resolved": "2.0.13",
+ "contentHash": "FPuyaXOb9LaD6nSUXtMrK/l564tmRbCfMiQWrnKzzLhJnnRuWkU2JpSJjV2KGCrjyx5ol7wy7TiK0GnGnPsIEA==",
+ "dependencies": {
+ "ColorCode.Core": "2.0.13",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.Common": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "KnHnukN+Sc26YT98OWYTp8mvaYlLc61lzDh0RrVRNQXm01hZ+iXAjCgKM59vAojqxNVrlbcXj22LYOyXWDItgg=="
+ },
+ "CommunityToolkit.WinUI": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "0O6hCHy+/adJygcROD3r3yA41gRq972i/r6uGUfo8lfEbr/I1YGePTClAh1P9JYT7DdoI2IqeUhX05lq+rwrHg==",
+ "dependencies": {
+ "CommunityToolkit.Common": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Core": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "7MVYQKjYlD5SryWNy5FA7Pcer9Rphjk7hCrSIOT9m4dcsOYmekZf36TOJARKxySXvlmjNud6QkmWssJKFC4k5w==",
+ "dependencies": {
+ "CommunityToolkit.WinUI": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.DataGrid": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "F73oYdYza8zhDwGHdXCZJJMeiDJ6nR97WPe180o7jOX3U90ZIqvU/GtYZdN3/x8DOS48t5GQG70LqxfyIGeaxw==",
+ "dependencies": {
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Input": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "fT8s21NI51YCR/mgm1eabwnSSQuXnQRz/TqHKjzYABhfGSvl44YlvuAQzbE9VfZSEUtiv4kesgylrzKd4/dArg==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Layout": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "FpKo2DdJgREAvttTYhOJTy1ru6ODRG41Da+vMrB7bcqavdbPgSTqYzolLcgvMl2InpIdt+fqn6U6mGQYoV+ksQ==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Markdown": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "0hAhwBfWa7aWKYOPGxhJJXowjrncY4he8jizcbuPVCgv8tZS1LXEEH4MoGKq57iLKz2lG3qaVN+1trcDWYq0Sg==",
+ "dependencies": {
+ "ColorCode.WinUI": "2.0.13",
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Core": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Media": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "FFH1mNF+rp3GEIQOceoxzSrRVY3G8aA+sYoK6Fv1kDEFWlCfLYF+cSCexL4sBuw0ARs1QXUvNqW4T1F/nAWsdw==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.Graphics.Win2D": "1.0.0.30",
+ "Microsoft.WindowsAppSDK": "1.0.0",
+ "System.Text.Json": "5.0.2"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "mNtVRpBVnFzSywRzzLPXBIoYm4UWJPZkpNPNAu75lnl4KcnkfjjyQg90hkfF9MT/JkBJQG0z5XOdMCksn7EiMQ==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "Google.Protobuf": {
+ "type": "Transitive",
+ "resolved": "3.23.4",
+ "contentHash": "DF+mB+Fwan5Hm5dnbKbrIl7C5ypMr8tJJheutkYgFXCoM88HfBNo2qYO60CEf6fvEe/fhCGtvfEBCoCIhIn7dQ=="
+ },
+ "Microsoft.Graphics.Win2D": {
+ "type": "Transitive",
+ "resolved": "1.0.0.30",
+ "contentHash": "pEGf7FSx2dRWJuoaSoXk+WYkZfYwhWoJKOyyo0XLRU6V2Ul02MjxRhoxggrzGz6jVFiT7R2NdPdV8M6N1F+QfA=="
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ },
+ "Microsoft.NETCore.Targets": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
+ },
+ "Microsoft.Win32.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "Microsoft.Win32.SystemEvents": {
+ "type": "Transitive",
+ "resolved": "7.0.0",
+ "contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
+ },
+ "NETStandard.Library": {
+ "type": "Transitive",
+ "resolved": "1.6.1",
+ "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.Win32.Primitives": "4.3.0",
+ "System.AppContext": "4.3.0",
+ "System.Collections": "4.3.0",
+ "System.Collections.Concurrent": "4.3.0",
+ "System.Console": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tools": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Calendars": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.Compression": "4.3.0",
+ "System.IO.Compression.ZipFile": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.Linq.Expressions": "4.3.0",
+ "System.Net.Http": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Net.Sockets": "4.3.0",
+ "System.ObjectModel": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Security.Cryptography.X509Certificates": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Text.Encoding.Extensions": "4.3.0",
+ "System.Text.RegularExpressions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "System.Threading.Timer": "4.3.0",
+ "System.Xml.ReaderWriter": "4.3.0",
+ "System.Xml.XDocument": "4.3.0"
+ }
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.IO.Compression": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
+ "dependencies": {
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "SharpCompress": {
+ "type": "Transitive",
+ "resolved": "0.31.0",
+ "contentHash": "wFf5N0ysnlKbG54beDDm4Z1uqM0EAKTupEkTxyG4EGVE1uZgTtohuBd2BhTHR2gNweJ6agxKbMFzmzk181qqjw=="
+ },
+ "System.AppContext": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==",
+ "dependencies": {
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Collections.Concurrent": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Console": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Diagnostics.DiagnosticSource": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Tools": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Tracing": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Calendars": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.Compression": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Buffers": "4.3.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.IO.Compression": "4.3.0"
+ }
+ },
+ "System.IO.Compression.ZipFile": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==",
+ "dependencies": {
+ "System.Buffers": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.Compression": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "7.0.0",
+ "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw=="
+ },
+ "System.Linq": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Linq.Expressions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.ObjectModel": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Emit.Lightweight": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Reflection.TypeExtensions": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.DiagnosticSource": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Extensions": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Security.Cryptography.X509Certificates": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Net.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Net.Sockets": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==",
+ "dependencies": {
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit.ILGeneration": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit.Lightweight": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.TypeExtensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices.RuntimeInformation": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "System.Runtime.Numerics": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
+ "dependencies": {
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Algorithms": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.Apple": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Cng": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Csp": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Collections.Concurrent": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
+ "dependencies": {
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.X509Certificates": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Calendars": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Cng": "4.3.0",
+ "System.Security.Cryptography.Csp": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "5.0.2",
+ "contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ=="
+ },
+ "System.Text.RegularExpressions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Threading.Timer": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Xml.ReaderWriter": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Text.Encoding.Extensions": "4.3.0",
+ "System.Text.RegularExpressions": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "System.Threading.Tasks.Extensions": "4.3.0"
+ }
+ },
+ "System.Xml.XDocument": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tools": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Xml.ReaderWriter": "4.3.0"
+ }
+ },
+ "colorthief": {
+ "type": "Project",
+ "dependencies": {
+ "System.Drawing.Common": "[7.0.0, )"
+ }
+ },
+ "hi3helper.core": {
+ "type": "Project",
+ "dependencies": {
+ "Hi3Helper.EncTool": "[1.0.0, )",
+ "Hi3Helper.Http": "[1.0.0, )",
+ "Hi3Helper.SharpHDiffPatch": "[1.0.0, )"
+ }
+ },
+ "hi3helper.enctool": {
+ "type": "Project",
+ "dependencies": {
+ "Google.Protobuf": "[3.23.4, )",
+ "Hi3Helper.Http": "[1.0.0, )",
+ "System.IO.Hashing": "[7.0.0, )"
+ }
+ },
+ "hi3helper.http": {
+ "type": "Project"
+ },
+ "hi3helper.sharphdiffpatch": {
+ "type": "Project"
+ }
+ },
+ "net7.0-windows10.0.22000": {
+ "Clowd.Squirrel": {
+ "type": "Direct",
+ "requested": "[2.9.42, )",
+ "resolved": "2.9.42",
+ "contentHash": "bM7h3tqoenZD+tmiV7pUnFdJ/o1oOrC21PaS8crMDRDOuGB4YqsgzlUKFD1g8X6z64IRBqzlUwEKzpsFyFc0mQ==",
+ "dependencies": {
+ "SharpCompress": "0.31.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI": {
+ "type": "Direct",
+ "requested": "[7.1.2, )",
+ "resolved": "7.1.2",
+ "contentHash": "jF1GdEJsZX5o81ZfLjSjgC5RuYwQneuW2mdFIb7FDFzITsgqCn7mfn7BglpNiXvjExkocmAKbBgmCcbp0Nypmw==",
+ "dependencies": {
+ "CommunityToolkit.WinUI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls": {
+ "type": "Direct",
+ "requested": "[7.1.2, )",
+ "resolved": "7.1.2",
+ "contentHash": "+aDc1KqmlYM+HE0Mw5OnfQBOFhY0c7zp1aGz/4qs+1I+Xk8Ot3IRwvs8dYxBEGCD9YzE2OzaJLPztBpQ9JEWig==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI.Controls.Core": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.DataGrid": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Input": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Layout": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Markdown": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Media": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "Microsoft.Windows.CsWinRT": {
+ "type": "Direct",
+ "requested": "[2.0.3, )",
+ "resolved": "2.0.3",
+ "contentHash": "viZIwWVUBp7x9QprOZbvocWasVIAfaXN2BK7tgMijYKe4X+WuU1m4RdqE8P2wv+o3q0Bk8mWsUFaMm36rsCvNg=="
+ },
+ "Microsoft.Windows.SDK.BuildTools": {
+ "type": "Direct",
+ "requested": "[10.0.22621.756, )",
+ "resolved": "10.0.22621.756",
+ "contentHash": "7ZL2sFSioYm1Ry067Kw1hg0SCcW5kuVezC2SwjGbcPE61Nn+gTbH86T73G3LcEOVj0S3IZzNuE/29gZvOLS7VA=="
+ },
+ "Microsoft.WindowsAppSDK": {
+ "type": "Direct",
+ "requested": "[1.3.230724000, )",
+ "resolved": "1.3.230724000",
+ "contentHash": "cCw26h8Uh8IjDMOUzHaR7/IKxEVJxuqEOgBlmLj0Pu1wDezZb9J0Wz53Vop10FQUOZaTfnwDcHavyPTxgkwbKQ==",
+ "dependencies": {
+ "Microsoft.Windows.SDK.BuildTools": "10.0.22621.1"
+ }
+ },
+ "System.CommandLine": {
+ "type": "Direct",
+ "requested": "[2.0.0-beta3.22114.1, )",
+ "resolved": "2.0.0-beta3.22114.1",
+ "contentHash": "QMzk1jj+PzdGbwuVsxII7FcQaCelnK+TcRcAqOGVoPovLBCSQPdikKiEzb56vAidvum5t4LSdDZ34O4j7+ALgw=="
+ },
+ "System.Drawing.Common": {
+ "type": "Direct",
+ "requested": "[7.0.0, )",
+ "resolved": "7.0.0",
+ "contentHash": "KIX+oBU38pxkKPxvLcLfIkOV5Ien8ReN78wro7OF5/erwcmortzeFx+iBswlh2Vz6gVne0khocQudGwaO1Ey6A==",
+ "dependencies": {
+ "Microsoft.Win32.SystemEvents": "7.0.0"
+ }
+ },
+ "ColorCode.Core": {
+ "type": "Transitive",
+ "resolved": "2.0.13",
+ "contentHash": "v0xqipj/6h2TpIKSrOCZpXMmOGvLsyO2prWBXY6t+lduexDSimqKIZXTTZkpq/vG2kNxB8K8nzyrkIB3usoN7A==",
+ "dependencies": {
+ "NETStandard.Library": "1.6.1"
+ }
+ },
+ "ColorCode.WinUI": {
+ "type": "Transitive",
+ "resolved": "2.0.13",
+ "contentHash": "FPuyaXOb9LaD6nSUXtMrK/l564tmRbCfMiQWrnKzzLhJnnRuWkU2JpSJjV2KGCrjyx5ol7wy7TiK0GnGnPsIEA==",
+ "dependencies": {
+ "ColorCode.Core": "2.0.13",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.Common": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "KnHnukN+Sc26YT98OWYTp8mvaYlLc61lzDh0RrVRNQXm01hZ+iXAjCgKM59vAojqxNVrlbcXj22LYOyXWDItgg=="
+ },
+ "CommunityToolkit.WinUI": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "0O6hCHy+/adJygcROD3r3yA41gRq972i/r6uGUfo8lfEbr/I1YGePTClAh1P9JYT7DdoI2IqeUhX05lq+rwrHg==",
+ "dependencies": {
+ "CommunityToolkit.Common": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Core": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "7MVYQKjYlD5SryWNy5FA7Pcer9Rphjk7hCrSIOT9m4dcsOYmekZf36TOJARKxySXvlmjNud6QkmWssJKFC4k5w==",
+ "dependencies": {
+ "CommunityToolkit.WinUI": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.DataGrid": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "F73oYdYza8zhDwGHdXCZJJMeiDJ6nR97WPe180o7jOX3U90ZIqvU/GtYZdN3/x8DOS48t5GQG70LqxfyIGeaxw==",
+ "dependencies": {
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Input": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "fT8s21NI51YCR/mgm1eabwnSSQuXnQRz/TqHKjzYABhfGSvl44YlvuAQzbE9VfZSEUtiv4kesgylrzKd4/dArg==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Layout": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "FpKo2DdJgREAvttTYhOJTy1ru6ODRG41Da+vMrB7bcqavdbPgSTqYzolLcgvMl2InpIdt+fqn6U6mGQYoV+ksQ==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Markdown": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "0hAhwBfWa7aWKYOPGxhJJXowjrncY4he8jizcbuPVCgv8tZS1LXEEH4MoGKq57iLKz2lG3qaVN+1trcDWYq0Sg==",
+ "dependencies": {
+ "ColorCode.WinUI": "2.0.13",
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "CommunityToolkit.WinUI.UI.Controls.Core": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Media": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "FFH1mNF+rp3GEIQOceoxzSrRVY3G8aA+sYoK6Fv1kDEFWlCfLYF+cSCexL4sBuw0ARs1QXUvNqW4T1F/nAWsdw==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.Graphics.Win2D": "1.0.0.30",
+ "Microsoft.WindowsAppSDK": "1.0.0",
+ "System.Text.Json": "5.0.2"
+ }
+ },
+ "CommunityToolkit.WinUI.UI.Controls.Primitives": {
+ "type": "Transitive",
+ "resolved": "7.1.2",
+ "contentHash": "mNtVRpBVnFzSywRzzLPXBIoYm4UWJPZkpNPNAu75lnl4KcnkfjjyQg90hkfF9MT/JkBJQG0z5XOdMCksn7EiMQ==",
+ "dependencies": {
+ "CommunityToolkit.WinUI.UI": "7.1.2",
+ "Microsoft.WindowsAppSDK": "1.0.0"
+ }
+ },
+ "Google.Protobuf": {
+ "type": "Transitive",
+ "resolved": "3.23.4",
+ "contentHash": "DF+mB+Fwan5Hm5dnbKbrIl7C5ypMr8tJJheutkYgFXCoM88HfBNo2qYO60CEf6fvEe/fhCGtvfEBCoCIhIn7dQ=="
+ },
+ "Microsoft.Graphics.Win2D": {
+ "type": "Transitive",
+ "resolved": "1.0.0.30",
+ "contentHash": "pEGf7FSx2dRWJuoaSoXk+WYkZfYwhWoJKOyyo0XLRU6V2Ul02MjxRhoxggrzGz6jVFiT7R2NdPdV8M6N1F+QfA=="
+ },
+ "Microsoft.NETCore.Platforms": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A=="
+ },
+ "Microsoft.NETCore.Targets": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
+ },
+ "Microsoft.Win32.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "Microsoft.Win32.SystemEvents": {
+ "type": "Transitive",
+ "resolved": "7.0.0",
+ "contentHash": "2nXPrhdAyAzir0gLl8Yy8S5Mnm/uBSQQA7jEsILOS1MTyS7DbmV1NgViMtvV1sfCD1ebITpNwb1NIinKeJgUVQ=="
+ },
+ "NETStandard.Library": {
+ "type": "Transitive",
+ "resolved": "1.6.1",
+ "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.Win32.Primitives": "4.3.0",
+ "System.AppContext": "4.3.0",
+ "System.Collections": "4.3.0",
+ "System.Collections.Concurrent": "4.3.0",
+ "System.Console": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tools": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Calendars": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.Compression": "4.3.0",
+ "System.IO.Compression.ZipFile": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.Linq.Expressions": "4.3.0",
+ "System.Net.Http": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Net.Sockets": "4.3.0",
+ "System.ObjectModel": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.InteropServices.RuntimeInformation": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Security.Cryptography.X509Certificates": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Text.Encoding.Extensions": "4.3.0",
+ "System.Text.RegularExpressions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "System.Threading.Timer": "4.3.0",
+ "System.Xml.ReaderWriter": "4.3.0",
+ "System.Xml.XDocument": "4.3.0"
+ }
+ },
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q=="
+ },
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA=="
+ },
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw=="
+ },
+ "runtime.native.System": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.IO.Compression": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==",
+ "dependencies": {
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0"
+ }
+ },
+ "runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==",
+ "dependencies": {
+ "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0",
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A=="
+ },
+ "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ=="
+ },
+ "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g=="
+ },
+ "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg=="
+ },
+ "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ=="
+ },
+ "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A=="
+ },
+ "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg=="
+ },
+ "SharpCompress": {
+ "type": "Transitive",
+ "resolved": "0.31.0",
+ "contentHash": "wFf5N0ysnlKbG54beDDm4Z1uqM0EAKTupEkTxyG4EGVE1uZgTtohuBd2BhTHR2gNweJ6agxKbMFzmzk181qqjw=="
+ },
+ "System.AppContext": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==",
+ "dependencies": {
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Collections": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Collections.Concurrent": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Console": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Debug": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Diagnostics.DiagnosticSource": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Tools": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Diagnostics.Tracing": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Calendars": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Globalization.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0"
+ }
+ },
+ "System.IO": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.Compression": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Buffers": "4.3.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.IO.Compression": "4.3.0"
+ }
+ },
+ "System.IO.Compression.ZipFile": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==",
+ "dependencies": {
+ "System.Buffers": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.Compression": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.IO.FileSystem.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.IO.Hashing": {
+ "type": "Transitive",
+ "resolved": "7.0.0",
+ "contentHash": "sDnWM0N3AMCa86LrKTWeF3BZLD2sgWyYUc7HL6z4+xyDZNQRwzmxbo4qP2rX2MqC+Sy1/gOSRDah5ltxY5jPxw=="
+ },
+ "System.Linq": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Linq.Expressions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.ObjectModel": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Emit.Lightweight": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Reflection.TypeExtensions": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Net.Http": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.DiagnosticSource": "4.3.0",
+ "System.Diagnostics.Tracing": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Extensions": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Security.Cryptography.X509Certificates": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Net.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Net.Sockets": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Net.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.ObjectModel": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Reflection": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==",
+ "dependencies": {
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit.ILGeneration": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Emit.Lightweight": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Emit.ILGeneration": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Reflection.TypeExtensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Resources.ResourceManager": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Globalization": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0"
+ }
+ },
+ "System.Runtime.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.Handles": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Primitives": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Handles": "4.3.0"
+ }
+ },
+ "System.Runtime.InteropServices.RuntimeInformation": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==",
+ "dependencies": {
+ "System.Reflection": "4.3.0",
+ "System.Reflection.Extensions": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0"
+ }
+ },
+ "System.Runtime.Numerics": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==",
+ "dependencies": {
+ "System.Globalization": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Algorithms": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.Apple": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Cng": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Csp": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Collections.Concurrent": "4.3.0",
+ "System.Linq": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.OpenSsl": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.Primitives": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==",
+ "dependencies": {
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Security.Cryptography.X509Certificates": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.Globalization.Calendars": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.Handles": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Runtime.Numerics": "4.3.0",
+ "System.Security.Cryptography.Algorithms": "4.3.0",
+ "System.Security.Cryptography.Cng": "4.3.0",
+ "System.Security.Cryptography.Csp": "4.3.0",
+ "System.Security.Cryptography.Encoding": "4.3.0",
+ "System.Security.Cryptography.OpenSsl": "4.3.0",
+ "System.Security.Cryptography.Primitives": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "runtime.native.System": "4.3.0",
+ "runtime.native.System.Net.Http": "4.3.0",
+ "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
+ }
+ },
+ "System.Text.Encoding": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Text.Encoding.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0",
+ "System.Text.Encoding": "4.3.0"
+ }
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "5.0.2",
+ "contentHash": "I47dVIGiV6SfAyppphxqupertT/5oZkYLDCX6vC3HpOI4ZLjyoKAreUoem2ie6G0RbRuFrlqz/PcTQjfb2DOfQ=="
+ },
+ "System.Text.RegularExpressions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==",
+ "dependencies": {
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==",
+ "dependencies": {
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Threading.Tasks.Extensions": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Threading.Tasks": "4.3.0"
+ }
+ },
+ "System.Threading.Timer": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==",
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.1.0",
+ "Microsoft.NETCore.Targets": "1.1.0",
+ "System.Runtime": "4.3.0"
+ }
+ },
+ "System.Xml.ReaderWriter": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.IO.FileSystem": "4.3.0",
+ "System.IO.FileSystem.Primitives": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Runtime.InteropServices": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Text.Encoding.Extensions": "4.3.0",
+ "System.Text.RegularExpressions": "4.3.0",
+ "System.Threading.Tasks": "4.3.0",
+ "System.Threading.Tasks.Extensions": "4.3.0"
+ }
+ },
+ "System.Xml.XDocument": {
+ "type": "Transitive",
+ "resolved": "4.3.0",
+ "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==",
+ "dependencies": {
+ "System.Collections": "4.3.0",
+ "System.Diagnostics.Debug": "4.3.0",
+ "System.Diagnostics.Tools": "4.3.0",
+ "System.Globalization": "4.3.0",
+ "System.IO": "4.3.0",
+ "System.Reflection": "4.3.0",
+ "System.Resources.ResourceManager": "4.3.0",
+ "System.Runtime": "4.3.0",
+ "System.Runtime.Extensions": "4.3.0",
+ "System.Text.Encoding": "4.3.0",
+ "System.Threading": "4.3.0",
+ "System.Xml.ReaderWriter": "4.3.0"
+ }
+ },
+ "colorthief": {
+ "type": "Project",
+ "dependencies": {
+ "System.Drawing.Common": "[7.0.0, )"
+ }
+ },
+ "hi3helper.core": {
+ "type": "Project",
+ "dependencies": {
+ "Hi3Helper.EncTool": "[1.0.0, )",
+ "Hi3Helper.Http": "[1.0.0, )",
+ "Hi3Helper.SharpHDiffPatch": "[1.0.0, )"
+ }
+ },
+ "hi3helper.enctool": {
+ "type": "Project",
+ "dependencies": {
+ "Google.Protobuf": "[3.23.4, )",
+ "Hi3Helper.Http": "[1.0.0, )",
+ "System.IO.Hashing": "[7.0.0, )"
+ }
+ },
+ "hi3helper.http": {
+ "type": "Project"
+ },
+ "hi3helper.sharphdiffpatch": {
+ "type": "Project"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ColorThief b/ColorThief
index 18b91a798..a79e0c132 160000
--- a/ColorThief
+++ b/ColorThief
@@ -1 +1 @@
-Subproject commit 18b91a798f51fd97478794b4ed22beb394a92c8f
+Subproject commit a79e0c132904eac83053406211701cc3f148443e
diff --git a/Hi3Helper.Core/Classes/Data/Tools/GenshinDispatchHelper/GenshinDispatchHelper.cs b/Hi3Helper.Core/Classes/Data/Tools/GenshinDispatchHelper/GenshinDispatchHelper.cs
index db4dd7805..d794f75cb 100644
--- a/Hi3Helper.Core/Classes/Data/Tools/GenshinDispatchHelper/GenshinDispatchHelper.cs
+++ b/Hi3Helper.Core/Classes/Data/Tools/GenshinDispatchHelper/GenshinDispatchHelper.cs
@@ -25,6 +25,10 @@ public class GenshinDispatchHelper : IDisposable
public GenshinDispatchHelper(int RegionID, string DispatchKey, string DispatchURLPrefix, string VersionString = "2.6.0", CancellationToken cancelToken = new CancellationToken())
{
+ if (RegionID == 4)
+ {
+ ChannelName = "CNRELWin";
+ }
this._httpClient = new Http.Http(false, 1, 1);
this.RegionSubdomain = GetSubdomainByRegionID(RegionID);
this.Version = VersionString;
@@ -49,7 +53,7 @@ public async Task LoadDispatchInfo()
#endif
await this._httpClient.Download(DispatchBaseURL, s, null, null, cancelToken).ConfigureAwait(false);
s.Position = 0;
- DispatcherDataInfo = (YSDispatchInfo)JsonSerializer.Deserialize(s, typeof(YSDispatchInfo), YSDispatchInfoContext.Default);
+ DispatcherDataInfo = (YSDispatchInfo)JsonSerializer.Deserialize(s, typeof(YSDispatchInfo), CoreLibraryJSONContext.Default);
}
return DispatcherDataInfo;
@@ -93,15 +97,15 @@ private void ParseDesignDataURL(ref QueryProperty ValProp)
{
(ValProp.ClientGameRes as List)
.Add(
- (PkgVersionProperties)JsonSerializer.Deserialize(Data, typeof(PkgVersionProperties), PkgVersionPropertiesContext.Default)
+ (PkgVersionProperties)JsonSerializer.Deserialize(Data, typeof(PkgVersionProperties), CoreLibraryJSONContext.Default)
);
}
}
private void ParseGameResPkgProp(ref QueryProperty ValProp)
{
- ValProp.ClientDesignData = (PkgVersionProperties)JsonSerializer.Deserialize(Gateway.GatewayProperties.RepoDesignDataJSON, typeof(PkgVersionProperties), PkgVersionPropertiesContext.Default);
- ValProp.ClientDesignDataSil = (PkgVersionProperties)JsonSerializer.Deserialize(Gateway.GatewayProperties.RepoDesignDataSilenceJSON, typeof(PkgVersionProperties), PkgVersionPropertiesContext.Default);
+ ValProp.ClientDesignData = (PkgVersionProperties)JsonSerializer.Deserialize(Gateway.GatewayProperties.RepoDesignDataJSON, typeof(PkgVersionProperties), CoreLibraryJSONContext.Default);
+ ValProp.ClientDesignDataSil = (PkgVersionProperties)JsonSerializer.Deserialize(Gateway.GatewayProperties.RepoDesignDataSilenceJSON, typeof(PkgVersionProperties), CoreLibraryJSONContext.Default);
}
private async Task ParseAudioAssetsURL(QueryProperty ValProp)
@@ -131,6 +135,7 @@ private string GetSubdomainByRegionID(int RegionID)
* 1 = Europe
* 2 = Asia
* 3 = TW/HK/MO
+ * 4 = Mainland China
*/
case 0:
return "osusadispatch";
@@ -140,6 +145,8 @@ private string GetSubdomainByRegionID(int RegionID)
return "osasiadispatch";
case 3:
return "oschtdispatch";
+ case 4:
+ return "cngfdispatch";
default:
throw new FormatException("Unknown region ID!");
}
diff --git a/Hi3Helper.Core/Classes/Data/Tools/HPatchTool.cs b/Hi3Helper.Core/Classes/Data/Tools/HPatchTool.cs
deleted file mode 100644
index dc617efec..000000000
--- a/Hi3Helper.Core/Classes/Data/Tools/HPatchTool.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using Hi3Helper.Shared.ClassStruct;
-using System;
-using System.IO;
-#if HDIFFEXPERIMENTAL
-using Hi3Helper.SharpHDiffPatch;
-#endif
-using static Hi3Helper.InvokeProp;
-
-namespace Hi3Helper.Data
-{
- public class HPatchUtil
- {
-#if HDIFFEXPERIMENTAL
- private HDiffPatch _patcher = new HDiffPatch();
-#endif
- uint bufSize = 0x10000;
-
- public void HPatchFile(string inputFile, string diffFile, string outputFile) =>
- GetEnumStatus(HPatch(
- inputFile, diffFile, outputFile,
- false, new UIntPtr(bufSize), 0,
- new FileInfo(diffFile).Length));
-
- public void HPatchDir(string inputPath, string diffFile, string outputPath)
- {
-#if HDIFFEXPERIMENTAL
- bool isInputAfile = File.Exists(inputPath) && !Directory.Exists(inputPath);
-
- if (isInputAfile)
- {
- _patcher.Initialize(diffFile);
- _patcher.Patch(inputPath, outputPath, false);
- return;
- }
-#endif
- string[] args = new string[] { "_", "-f", "-s", inputPath, diffFile, outputPath };
-
- GetEnumStatus(HPatchCommand(args.Length, args));
- }
-
- void GetEnumStatus(int i)
- {
- switch ((HPatchUtilStat)i)
- {
- case HPatchUtilStat.HPATCH_SUCCESS: return;
- case HPatchUtilStat.HPATCH_MEM_ERROR:
- throw new OutOfMemoryException($"Out Of Memory. ERRMSG: {(HPatchUtilStat)i}");
- default:
- throw new Exception($"Unhandled Error. ERRMSG: {(HPatchUtilStat)i}");
- }
- }
- }
-}
diff --git a/Hi3Helper.Core/Classes/DiscordPresence/DiscordPresenceManager.cs b/Hi3Helper.Core/Classes/DiscordPresence/DiscordPresenceManager.cs
index c11ec91ee..4d86712d4 100644
--- a/Hi3Helper.Core/Classes/DiscordPresence/DiscordPresenceManager.cs
+++ b/Hi3Helper.Core/Classes/DiscordPresence/DiscordPresenceManager.cs
@@ -218,12 +218,13 @@ private void BuildActivityGameStatus(string activityName, bool isGameStatusEnabl
_activity = new Activity
{
Details = $"{activityName} {(!isGameStatusEnabled ? ConfigV2Store.CurrentConfigV2GameCategory : Lang._Misc.DiscordRP_Ad)}",
- State = $"Server: {ConfigV2Store.CurrentConfigV2GameRegion}",
+ State = $"{Lang._Misc.DiscordRP_Region} {ConfigV2Store.CurrentConfigV2GameRegion}",
Assets = new ActivityAssets
{
LargeImage = $"game-{ConfigV2Store.CurrentConfigV2.GameType.ToString().ToLower()}-logo",
LargeText = $"{ConfigV2Store.CurrentConfigV2GameCategory} - {ConfigV2Store.CurrentConfigV2GameRegion}",
- SmallImage = $"launcher-logo"
+ SmallImage = $"launcher-logo",
+ SmallText = $"Collapse Launcher v{AppCurrentVersionString} {(IsPreview ? "Preview" : "Stable")}"
},
Timestamps = new ActivityTimestamps
{
@@ -247,21 +248,20 @@ private void BuildActivityAppStatus(string activityName, bool isGameStatusEnable
_activity = new Activity
{
Details = $"{activityName} {(!isGameStatusEnabled ? string.Empty : Lang._Misc.DiscordRP_Ad)}",
- State = $"Server: {ConfigV2Store.CurrentConfigV2GameRegion}",
+ State = $"{Lang._Misc.DiscordRP_Region} {ConfigV2Store.CurrentConfigV2GameRegion}",
Assets = new ActivityAssets
{
LargeImage = $"game-{ConfigV2Store.CurrentConfigV2.GameType.ToString().ToLower()}-logo",
LargeText = $"{ConfigV2Store.CurrentConfigV2GameCategory}",
- SmallImage = $"launcher-logo"
+ SmallImage = $"launcher-logo",
+ SmallText = $"Collapse Launcher v{AppCurrentVersionString} {(IsPreview ? "Preview" : "Stable")}"
},
};
}
private void UpdateActivity() => _activityManager?.UpdateActivity(_activity, (a) =>
{
-#if DEBUG
Logger.LogWriteLine($"Activity updated! => {_activity.Details} - {_activity.State}");
-#endif
});
private void UpdateCallbacksRoutine()
diff --git a/Hi3Helper.Core/Classes/Preset/Classes/ClassesContext.cs b/Hi3Helper.Core/Classes/Preset/Classes/ClassesContext.cs
index aa5338816..7d13b8de7 100644
--- a/Hi3Helper.Core/Classes/Preset/Classes/ClassesContext.cs
+++ b/Hi3Helper.Core/Classes/Preset/Classes/ClassesContext.cs
@@ -7,55 +7,22 @@
namespace Hi3Helper
{
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(YSDispatchInfo))]
- internal sealed partial class YSDispatchInfoContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(PkgVersionProperties))]
- public sealed partial class PkgVersionPropertiesContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = true, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(LocalizationParams))]
- internal sealed partial class LocalizationParamsContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(GeneralDataProp))]
- internal sealed partial class GeneralDataPropContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(Metadata))]
- internal sealed partial class MetadataContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSourceGenerationOptions(IncludeFields = true, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = false)]
[JsonSerializable(typeof(Stamp))]
- public sealed partial class StampContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(Metadata))]
[JsonSerializable(typeof(BHI3LInfo))]
- public sealed partial class BHI3LInfoContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(DataProperties))]
- public sealed partial class DataPropertiesContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
- [JsonSerializable(typeof(DataPropertiesContent))]
- public sealed partial class DataPropertiesContentContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(YSDispatchInfo))]
+ [JsonSerializable(typeof(GeneralDataProp))]
[JsonSerializable(typeof(RegionResourceProp))]
- public sealed partial class RegionResourcePropContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(PkgVersionProperties))]
+ [JsonSerializable(typeof(DataPropertiesContent))]
[JsonSerializable(typeof(FilePropertiesRemote[]))]
- public sealed partial class Array_FilePropertiesRemoteContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(List))]
- public sealed partial class L_FilePropertiesRemoteContext : JsonSerializerContext { }
-
- [JsonSourceGenerationOptions(IncludeFields = false, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
[JsonSerializable(typeof(Dictionary))]
- public sealed partial class D_StringString : JsonSerializerContext { }
+ public sealed partial class CoreLibraryJSONContext : JsonSerializerContext { }
+
+ [JsonSourceGenerationOptions(IncludeFields = true, GenerationMode = JsonSourceGenerationMode.Metadata, IgnoreReadOnlyFields = true)]
+ [JsonSerializable(typeof(LocalizationParams))]
+ internal sealed partial class CoreLibraryFieldsJSONContext : JsonSerializerContext { }
}
diff --git a/Hi3Helper.Core/Classes/Preset/Classes/PresetConfigV2.cs b/Hi3Helper.Core/Classes/Preset/Classes/PresetConfigV2.cs
index 272615ca3..c03ef6e9b 100644
--- a/Hi3Helper.Core/Classes/Preset/Classes/PresetConfigV2.cs
+++ b/Hi3Helper.Core/Classes/Preset/Classes/PresetConfigV2.cs
@@ -104,9 +104,26 @@ public void DecryptStrings()
}
}
}
+
+ public void GenerateHashID()
+ {
+ foreach (KeyValuePair> game in MetadataV2)
+ {
+ foreach (KeyValuePair region in game.Value)
+ {
+ string HashComposition = $"{ConverterTool.GetUnixTimestamp(true)} - {game.Key} - {region.Value.ZoneName}";
+ int HashID = ConverterTool.BytesToCRC32Int(HashComposition);
+ region.Value.HashID = HashID;
+ region.Value.GameName = game.Key;
+
+ LogWriteLine($"Cur. Session Region Hash: {HashID} ({HashComposition})", LogType.Default, true);
+ }
+ }
+ }
#nullable enable
}
+ [Serializable]
public sealed class PresetConfigV2
{
private const string PrefixRegInstallLocation = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{0}";
@@ -226,7 +243,7 @@ private int GetVoiceLanguageID_Genshin(string RegPath)
}
regValue = Encoding.UTF8.GetString(value).AsSpan().Trim('\0');
- GeneralDataProp? RegValues = (GeneralDataProp?)JsonSerializer.Deserialize(new string(regValue), typeof(GeneralDataProp), GeneralDataPropContext.Default);
+ GeneralDataProp? RegValues = (GeneralDataProp?)JsonSerializer.Deserialize(new string(regValue), typeof(GeneralDataProp), CoreLibraryJSONContext.Default);
return RegValues?.deviceVoiceLanguageType ?? 2;
}
catch (JsonException ex)
@@ -274,13 +291,13 @@ private void SetVoiceLanguageID_Genshin(int LangID)
result = (byte[]?)keys.GetValue("GENERAL_DATA_h2389025596");
if (result is null) return;
regValue = Encoding.UTF8.GetString(result).AsSpan().Trim('\0');
- initValue = (GeneralDataProp?)JsonSerializer.Deserialize(new string(regValue), typeof(GeneralDataProp), GeneralDataPropContext.Default) ?? initValue;
+ initValue = (GeneralDataProp?)JsonSerializer.Deserialize(new string(regValue), typeof(GeneralDataProp), CoreLibraryJSONContext.Default) ?? initValue;
}
initValue.deviceVoiceLanguageType = LangID;
keys.SetValue("GENERAL_DATA_h2389025596",
Encoding.UTF8.GetBytes(
- JsonSerializer.Serialize(initValue, typeof(GeneralDataProp), GeneralDataPropContext.Default) + '\0'));
+ JsonSerializer.Serialize(initValue, typeof(GeneralDataProp), CoreLibraryJSONContext.Default) + '\0'));
}
catch (Exception ex)
{
@@ -325,7 +342,7 @@ public int GetRegServerNameID()
try
{
- return (int?)(((GeneralDataProp?)JsonSerializer.Deserialize(regValue, typeof(GeneralDataProp), GeneralDataPropContext.Default))?.selectedServerName) ?? 0;
+ return (int?)(((GeneralDataProp?)JsonSerializer.Deserialize(regValue, typeof(GeneralDataProp), CoreLibraryJSONContext.Default))?.selectedServerName) ?? 0;
}
catch (Exception ex)
{
@@ -453,6 +470,8 @@ private bool CheckInnerGameConfig(in string GamePath)
return File.Exists(Path.Combine(ActualGameDataLocation, "config.ini")) && File.Exists(Path.Combine(ActualGameDataLocation, GameExecutableName));
}
+ public string? GameName { get; set; }
+ public int HashID { get; set; }
private string? SystemDriveLetter { get => Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System)); }
public string? ProfileName { get; set; }
public GameChannel GameChannel { get; set; } = GameChannel.Stable;
diff --git a/Hi3Helper.Core/Classes/Shared/ClassStruct/Class/RegionResource.cs b/Hi3Helper.Core/Classes/Shared/ClassStruct/Class/RegionResource.cs
index 557a55b78..84f25c7ec 100644
--- a/Hi3Helper.Core/Classes/Shared/ClassStruct/Class/RegionResource.cs
+++ b/Hi3Helper.Core/Classes/Shared/ClassStruct/Class/RegionResource.cs
@@ -5,13 +5,33 @@
namespace Hi3Helper.Shared.ClassStruct
{
- public class RegionResourceProp
+ public interface IRegionResourceCopyable
+ {
+ T Copy();
+ }
+
+ public static class RegionResourceListHelper
+ {
+ public static List Copy(this List source)
+ where T : IRegionResourceCopyable
+ {
+ if (source == null) return null;
+ return new List(source);
+ }
+ }
+
+ public class RegionResourceProp : IRegionResourceCopyable
{
public RegionResourceGame data { get; set; }
public string imgLocalPath { get; set; } = string.Empty;
+ public RegionResourceProp Copy() => new RegionResourceProp()
+ {
+ data = data?.Copy(),
+ imgLocalPath = imgLocalPath
+ };
}
- public class RegionResourceGame
+ public class RegionResourceGame : IRegionResourceCopyable
{
public RegionResourceLatest game { get; set; }
public RegionResourceLatest pre_download_game { get; set; }
@@ -19,15 +39,29 @@ public class RegionResourceGame
public List banner { get; set; }
public List icon { get; set; }
public List post { get; set; }
+ public RegionResourceGame Copy() => new RegionResourceGame()
+ {
+ game = game?.Copy(),
+ pre_download_game = pre_download_game?.Copy(),
+ adv = adv?.Copy(),
+ banner = banner?.Copy(),
+ icon = icon?.Copy(),
+ post = post?.Copy()
+ };
}
- public class RegionResourceLatest
+ public class RegionResourceLatest : IRegionResourceCopyable
{
public RegionResourceVersion latest { get; set; }
public List diffs { get; set; }
+ public RegionResourceLatest Copy() => new RegionResourceLatest()
+ {
+ latest = latest?.Copy(),
+ diffs = diffs?.Copy()
+ };
}
- public class RegionResourceVersion
+ public class RegionResourceVersion : IRegionResourceCopyable
{
public string version { get; set; }
public string path { get; set; }
@@ -44,25 +78,52 @@ public class RegionResourceVersion
public string entry { get; set; }
public List voice_packs { get; set; }
public List segments { get; set; }
+ public RegionResourceVersion Copy() => new RegionResourceVersion()
+ {
+ version = version,
+ path = path,
+ decompressed_path = decompressed_path,
+ size = size,
+ package_size = package_size,
+ md5 = md5,
+ language = language,
+ languageID = languageID,
+ is_recommended_update = is_recommended_update,
+ entry = entry,
+ voice_packs = voice_packs?.Copy(),
+ segments = segments?.Copy()
+ };
}
- public class HomeMenuPanel
+ public class HomeMenuPanel : IRegionResourceCopyable
{
public List sideMenuPanel { get; set; }
public List imageCarouselPanel { get; set; }
public PostCarouselTypes articlePanel { get; set; }
public RegionBackgroundProp eventPanel { get; set; }
- public HomeMenuPanel Copy() => this;
+ public HomeMenuPanel Copy() => new HomeMenuPanel()
+ {
+ sideMenuPanel = sideMenuPanel?.Copy(),
+ imageCarouselPanel = imageCarouselPanel?.Copy(),
+ articlePanel = articlePanel?.Copy(),
+ eventPanel = eventPanel?.Copy()
+ };
}
- public class PostCarouselTypes
+ public class PostCarouselTypes : IRegionResourceCopyable
{
public List Events { get; set; } = new List();
public List Notices { get; set; } = new List();
public List Info { get; set; } = new List();
+ public PostCarouselTypes Copy() => new PostCarouselTypes()
+ {
+ Events = Events?.Copy(),
+ Notices = Notices?.Copy(),
+ Info = Info?.Copy()
+ };
}
- public class MenuPanelProp
+ public class MenuPanelProp : IRegionResourceCopyable
{
public string URL { get; set; }
public string Icon { get; set; }
@@ -73,9 +134,18 @@ public class MenuPanelProp
public string Description { get; set; }
public bool IsDescriptionExist => !string.IsNullOrEmpty(Description);
public bool IsQRDescriptionExist => !string.IsNullOrEmpty(QR_Description);
+ public MenuPanelProp Copy() => new MenuPanelProp()
+ {
+ URL = URL,
+ Icon = Icon,
+ IconHover = IconHover,
+ QR = QR,
+ QR_Description = QR_Description,
+ Description = Description
+ };
}
- public class RegionBackgroundProp
+ public class RegionBackgroundProp : IRegionResourceCopyable
{
public string background { get; set; }
public string bg_checksum { get; set; }
@@ -83,6 +153,15 @@ public class RegionBackgroundProp
public string url { get; set; }
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
public int? version { get; set; }
+
+ public RegionBackgroundProp Copy() => new RegionBackgroundProp
+ {
+ background = background,
+ bg_checksum = bg_checksum,
+ icon = icon,
+ url = url,
+ version = version
+ };
}
[JsonConverter(typeof(JsonStringEnumConverter))]
@@ -93,7 +172,7 @@ public enum PostCarouselType
POST_TYPE_ANNOUNCE
}
- public class RegionSocMedProp
+ public class RegionSocMedProp : IRegionResourceCopyable
{
private string _url;
@@ -128,6 +207,21 @@ private unsafe string StripTabsAndNewlines(ReadOnlySpan s)
}
return new string(newChars, 0, (int)(currentChar - newChars));
}
+
+ public RegionSocMedProp Copy() => new RegionSocMedProp()
+ {
+ icon_id = icon_id,
+ icon_link = icon_link,
+ img = img,
+ img_hover = img_hover,
+ qr_img = qr_img,
+ qr_desc = qr_desc,
+ url = url,
+ name = name,
+ title = title,
+ show_time = show_time,
+ type = type
+ };
}
public class YSDispatchInfo
diff --git a/Hi3Helper.Core/Classes/Shared/GameConversion/CheckIntegrity.cs b/Hi3Helper.Core/Classes/Shared/GameConversion/CheckIntegrity.cs
deleted file mode 100644
index 08c8d2e04..000000000
--- a/Hi3Helper.Core/Classes/Shared/GameConversion/CheckIntegrity.cs
+++ /dev/null
@@ -1,269 +0,0 @@
-using Force.Crc32;
-using Hi3Helper.Data;
-using Hi3Helper.Preset;
-using Hi3Helper.Shared.ClassStruct;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Text.Json;
-using System.Threading;
-using System.Threading.Tasks;
-using static Hi3Helper.Data.ConverterTool;
-using static Hi3Helper.Locale;
-
-namespace Hi3Helper.Shared.GameConversion
-{
- public class CheckIntegrity
- {
- private string targetPath;
- private string repoIndexURL;
- private Http.Http http;
- private Stream stream;
- private CancellationTokenSource tokenSource;
- private Stopwatch sw;
-
- private List FileIndexesProperty = new List();
- private List BrokenFileIndexesProperty = new List();
-
- public event EventHandler ProgressChanged;
-
- private string CheckStatus;
- private long TotalSizeToRead, TotalRead;
- private int TotalCountToRead, TotalCount;
-
- private string FilePath, FileCRC;
- private FileInfo FileInfo;
- private FilePropertiesRemote FileIndex;
- private Crc32Algorithm FileCRCTool;
- private byte[] buffer = new byte[0x400000];
-
- public CheckIntegrity(string targetPath, string repoURL, string repoIndexURL, CancellationTokenSource tokenSource)
- {
- this.sw = Stopwatch.StartNew();
- this.targetPath = targetPath;
- this.repoIndexURL = repoIndexURL;
- this.tokenSource = tokenSource;
- this.http = new Http.Http();
- }
-
- public async Task StartCheckIntegrity()
- {
- File.Create(Path.Combine(targetPath, "_conversion_unfinished")).Close();
- await FetchAPI();
- await Task.Run(CheckGameFiles);
- stream.Dispose();
- FileIndexesProperty.Clear();
- }
-
- private async Task FetchAPI()
- {
- CheckStatus = Lang._InstallMigrateSteam.Step3Subtitle;
-
- using (stream = new MemoryStream())
- {
- http.DownloadProgress += HttpAdapter;
- await http.Download(repoIndexURL, stream, null, null, tokenSource.Token);
- http.DownloadProgress -= HttpAdapter;
-
- FileIndexesProperty = (List)JsonSerializer.Deserialize(stream, typeof(List), L_FilePropertiesRemoteContext.Default);
- }
- }
-
- public List GetNecessaryFileList() => BrokenFileIndexesProperty;
-
- private void CheckGameFiles()
- {
- sw = Stopwatch.StartNew();
-
- TotalCount = 0;
- TotalRead = 0;
- TotalSizeToRead = FileIndexesProperty.Sum(x => x.S)
- + FileIndexesProperty.Where(x => x.BlkC != null).Sum(x => x.BlkC.Sum(x => x.BlockSize));
-
- TotalCountToRead = FileIndexesProperty.Count
- + FileIndexesProperty.Where(x => x.BlkC != null).Sum(y => y.BlkC.Sum(z => z.BlockContent.Count));
-
- foreach (FilePropertiesRemote Index in FileIndexesProperty)
- {
- FilePath = Path.Combine(targetPath, NormalizePath(Index.N));
- FileInfo = new FileInfo(FilePath);
- FileIndex = Index;
-
- switch (Index.FT)
- {
- case FileType.Generic:
- case FileType.Audio:
- CheckGenericAudioFile();
- break;
- case FileType.Blocks:
- CheckBlockFile();
- break;
- }
- }
- }
-
- private void CheckGenericAudioFile()
- {
- TotalCount++;
- CheckStatus = string.Format(Lang._InstallMigrateSteam.InnerCheckFile, FileIndex.FT, TotalCount, TotalCountToRead, FileIndex.N);
- if (!FileInfo.Exists)
- {
- TotalRead += FileIndex.S;
- BrokenFileIndexesProperty.Add(FileIndex);
- return;
- }
-
- using (stream = FileInfo.OpenRead())
- if ((FileCRC = GenerateCRC(stream)) != FileIndex.CRC)
- BrokenFileIndexesProperty.Add(FileIndex);
- }
-
- private void CheckBlockFile()
- {
- List