diff --git a/CollapseLauncher/Classes/CachesManagement/Honkai/Update.cs b/CollapseLauncher/Classes/CachesManagement/Honkai/Update.cs index 7c03ca2c26..9a13041d16 100644 --- a/CollapseLauncher/Classes/CachesManagement/Honkai/Update.cs +++ b/CollapseLauncher/Classes/CachesManagement/Honkai/Update.cs @@ -39,7 +39,7 @@ private async Task Update(List updateAssetIndex, List assetProperty = [.. AssetEntry]; + ObservableCollection assetProperty = [.. AssetEntry]; ConcurrentDictionary<(CacheAsset, IAssetProperty), byte> runningTask = new(); if (IsBurstDownloadEnabled) diff --git a/CollapseLauncher/Classes/Extension/NumberExtensions.cs b/CollapseLauncher/Classes/Extension/NumberExtensions.cs index 66256384d1..3bbae05077 100644 --- a/CollapseLauncher/Classes/Extension/NumberExtensions.cs +++ b/CollapseLauncher/Classes/Extension/NumberExtensions.cs @@ -1,6 +1,7 @@ using Hi3Helper.Shared.Region; using System; using System.Runtime.CompilerServices; +#pragma warning disable IDE0130 namespace CollapseLauncher.Extension { @@ -8,8 +9,13 @@ internal static class NumberExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static double ClampLimitedSpeedNumber(this double speed) - => LauncherConfig.DownloadSpeedLimitCached > 0 ? - Math.Min(LauncherConfig.DownloadSpeedLimitCached, speed) : - speed; + { + return speed; + /* + return LauncherConfig.DownloadSpeedLimit > 0 ? + Math.Min(LauncherConfig.DownloadSpeedLimit, speed) : + speed; + */ + } } } diff --git a/CollapseLauncher/Classes/Helper/SpeedLimiterService.cs b/CollapseLauncher/Classes/Helper/SpeedLimiterService.cs new file mode 100644 index 0000000000..302a536f28 --- /dev/null +++ b/CollapseLauncher/Classes/Helper/SpeedLimiterService.cs @@ -0,0 +1,348 @@ +using CollapseLauncher.Interfaces.Class; +using CollapseLauncher.Plugins; +using Hi3Helper; +using Hi3Helper.Http; +using Hi3Helper.Shared.Region; +using Hi3Helper.Sophon; +using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using System.Threading.Tasks.Sources; +using WinRT; +// ReSharper disable CheckNamespace +#pragma warning disable IDE0130 + +#nullable enable +namespace CollapseLauncher.Helper; + +/// +/// Provides a helper for using Speed Limiter Service. +/// +/// +/// You can call method to pass the read bytes to the service and then throttle the speed for you. +///

+/// Usage example on your code: +/// +/// async Task ReadDataAsync(Stream inputStream, Stream outputStream, CancellationToken token) +/// { +/// byte[] buffer = new byte[8192]; +/// int read; +/// +/// nint context = SpeedLimiterService.CreateServiceContext(); +/// while ((read = await inputStream.ReadAsync(buffer, 0, buffer.Length, token)) > 0) +/// { +/// // Do anything... +/// ... +/// +/// // Pass the read bytes to the speed limiter service, and wait if necessary until the service allows more bytes to be processed. +/// await SpeedLimiterService.AddBytesOrWaitAsync(context, read, token); +/// } +/// } +/// +///
+[GeneratedBindableCustomProperty] +public partial class SpeedLimiterService : NotifyPropertyChanged +{ + private const string LibName = @"Lib\Hi3Helper.Throttle.dll"; + private const string SetSharedThrottleBytesExportName = "ThrottleServiceSetSharedThrottleBytes"; + private const string GetSharedThrottleBytesExportName = "ThrottleServiceGetSharedThrottleBytes"; + private const string AddBytesOrWaitAsyncExportName = "ThrottleServiceAddBytesOrWaitAsync"; + + [LibraryImport(LibName, EntryPoint = SetSharedThrottleBytesExportName)] + [return: MarshalAs(UnmanagedType.Error)] + private static partial int ThrottleServiceSetSharedThrottleBytes(long bytesPerSecond, in long burstBytes); + + [LibraryImport(LibName, EntryPoint = GetSharedThrottleBytesExportName)] + private static partial void ThrottleServiceGetSharedThrottleBytes(ref long bytesPerSecond, ref long burstBytes); + + [LibraryImport(LibName, EntryPoint = AddBytesOrWaitAsyncExportName)] + [return: MarshalAs(UnmanagedType.Error)] + private static partial int ThrottleServiceAddBytesOrWaitAsync( + nint context, + long readBytes, + nint tokenHandle, + out nint asyncWaitHandle); + + public static SpeedLimiterService Shared { get; } = new(); + + public static readonly nint AddBytesOrWaitAsyncDelegatePtr; + public static readonly nint SetSharedThrottleBytesDelegatePtr; + public static readonly nint GetSharedThrottleBytesDelegatePtr; + + static SpeedLimiterService() + { + if (!NativeLibrary.TryLoad(LibName, out nint libHandle)) + { + throw new DllNotFoundException($"Failed to load {LibName} library!"); + } + + LoadExport(libHandle, AddBytesOrWaitAsyncExportName, out AddBytesOrWaitAsyncDelegatePtr); + LoadExport(libHandle, SetSharedThrottleBytesExportName, out SetSharedThrottleBytesDelegatePtr); + LoadExport(libHandle, GetSharedThrottleBytesExportName, out GetSharedThrottleBytesDelegatePtr); + + if (Shared.IsEnabled) + { + ToggleSophonService(true); + TogglePluginService(true); + ToggleHi3HelperHttpService(true); + } + + UpdateChanges(); + return; + + static void LoadExport(nint handle, string name, out nint exportPtr) + { + if (!NativeLibrary.TryGetExport(handle, name, out exportPtr)) + { + throw new + EntryPointNotFoundException($"Cannot find {AddBytesOrWaitAsyncExportName} export from library!"); + } + } + } + + public bool IsEnabled + { + get => LauncherConfig.IsUseDownloadSpeedLimiter; + set + { + LauncherConfig.IsUseDownloadSpeedLimiter = value; + + UpdateChanges(); + ToggleSophonService(value); + TogglePluginService(value); + ToggleHi3HelperHttpService(value); + OnPropertyChanged(); + } + } + + public double CurrentThrottleMebiBytes + { + get => (double)LauncherConfig.DownloadSpeedLimit / (1 << 20); + set + { + LauncherConfig.DownloadSpeedLimit = (long)(value * (1 << 20)); + OnPropertyChanged(); + UpdateChanges(); + } + } + + private static void UpdateChanges() + { + const long burstMultiply = 2; + + bool isEnabled = Shared.IsEnabled; + long currentSetBytes = (long)(Shared.CurrentThrottleMebiBytes * (1 << 20)); + + // Override throttle bytes to 0 if disabled. + if (!isEnabled || currentSetBytes < 0) + { + currentSetBytes = 0; + } + + int hr = ThrottleServiceSetSharedThrottleBytes(currentSetBytes, currentSetBytes * burstMultiply); + + long bytesRead = 0; + long burstBytes = 0; + ThrottleServiceGetSharedThrottleBytes(ref bytesRead, ref burstBytes); + + if (Marshal.GetExceptionForHR(hr) is {} exception) + { + Logger.LogWriteLine($"Failed while trying to set throttle bytes value to: {currentSetBytes} bytes.\r\n{exception}", + LogType.Error, + true); + } + } + + private static void TogglePluginService(bool isEnabled) + { + foreach (KeyValuePair plugin in PluginManager.PluginInstances) + { + plugin.Value.ToggleSpeedLimiterService(isEnabled); + } + } + + private static void ToggleSophonService(bool isEnabled) + { + SophonDownloadSpeedLimiter.AddBytesOrWaitAsyncDelegate = isEnabled + ? AddBytesOrWaitAsync + : null; + } + + private static void ToggleHi3HelperHttpService(bool isEnabled) + { + DownloadSpeedLimiter.AddBytesOrWaitAsyncDelegate = isEnabled + ? AddBytesOrWaitAsync + : null; + } + + /// + /// Creates a context to be used for the speed limiter service. This context can be used into multiple instances or threads of your downloader. + /// + public static unsafe nint CreateServiceContext() + { + long bytesPerSecond = 0; + long burstBytes = 0; + ThrottleServiceGetSharedThrottleBytes(ref bytesPerSecond, ref burstBytes); + + nint ptr = (nint)NativeMemory.Alloc(2, 8); // Context struct is 16 bytes in size. + + // Preallocate tokens and last timestamp + ThrottleServiceContext* ptrContext = (ThrottleServiceContext*)ptr; + ptrContext->AvailableTokens = burstBytes < bytesPerSecond ? bytesPerSecond * 2 : burstBytes; + ptrContext->LastTimestamp = Environment.TickCount64; + + return ptr; + } + + /// + /// Free the speed limiter service context. + /// + /// + public static unsafe void FreeServiceContext(nint context) + { + if (context != nint.Zero) + { + NativeMemory.Free((void*)context); + } + } + + /// + /// Adds-up counter of the consumed bytes into the service, and await (throttle) if the target speed is already reached.
+ /// If the service is not registered or the callback is not set, this method will simply return immediately without awaiting. + ///
+ /// The pointer of the service context. + /// How many bytes consumed on current operation. + /// Cancellation token for the async operation. + [SkipLocalsInit] + public static ValueTask AddBytesOrWaitAsync( + nint context, + long readBytes, + CancellationToken token = default) + { + if (context == nint.Zero) + return ValueTask.CompletedTask; + + int hr = ThrottleServiceAddBytesOrWaitAsync(context, + readBytes, + nint.Zero, + out nint completionHandle); + + if (Marshal.GetExceptionForHR(hr) is { } ex) + return ValueTask.FromException(ex); + + NativeThrottleOperation op = new(); + op.Initialize(completionHandle, token); + + return op.AsValueTask(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 8)] // Pack to 8 bytes to ensure aligning + private struct ThrottleServiceContext + { + public long AvailableTokens; + public long LastTimestamp; + } + + internal sealed class NativeThrottleOperation : IValueTaskSource + { + private ManualResetValueTaskSourceCore _core = new() + { + RunContinuationsAsynchronously = true + }; + + private int _isCompleted; + private EventWaitHandle? _completionWait; + private SafeWaitHandle? _completionSafe; + private RegisteredWaitHandle? _registeredWait; + private CancellationTokenRegistration _ctr; + + public ValueTask AsValueTask() + => new(this, _core.Version); + + public void Initialize( + nint completionHandle, + CancellationToken token) + { + _completionSafe = new SafeWaitHandle(completionHandle, true); + _completionWait = new EventWaitHandle(false, EventResetMode.ManualReset) + { + SafeWaitHandle = _completionSafe + }; + + _registeredWait = + ThreadPool.RegisterWaitForSingleObject(_completionWait, + OnWaitSingleCompleted, + this, + -1, + true); + + if (token.CanBeCanceled) + { + _ctr = token.Register(OnCancellationRequested, this); + } + } + + private static void OnWaitSingleCompleted(object? state, bool isTimedOut) + { + NativeThrottleOperation op = (NativeThrottleOperation)state!; + op.Complete(); + } + + private static void OnCancellationRequested(object? state) + { + NativeThrottleOperation op = (NativeThrottleOperation)state!; + op.Cancel(); + } + + private void Complete() + { + if (Interlocked.Exchange(ref _isCompleted, 1) == 1) + { + return; + } + + Cleanup(); + _core.SetResult(true); + } + + private void Cancel() + { + if (Interlocked.Exchange(ref _isCompleted, 1) == 1) + { + return; + } + + Cleanup(); + _core.SetException(new OperationCanceledException()); + } + + private void Cleanup() + { + _registeredWait?.Unregister(null); + _registeredWait = null; + + _ctr.Dispose(); + + _completionWait?.Dispose(); + _completionWait = null; + _completionSafe = null; + } + + public void GetResult(short token) + => _core.GetResult(token); + + public ValueTaskSourceStatus GetStatus(short token) + => _core.GetStatus(token); + + public void OnCompleted( + Action continuation, + object? state, + short token, + ValueTaskSourceOnCompletedFlags flags) + => _core.OnCompleted(continuation, state, token, flags); + } +} diff --git a/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.Sophon.cs b/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.Sophon.cs index bb45776e91..e613fda0f8 100644 --- a/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.Sophon.cs +++ b/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.Sophon.cs @@ -166,7 +166,7 @@ protected virtual async Task StartPackageInstallSophon(GameInstallStateEnum game { // Create a sophon download speed limiter instance SophonDownloadSpeedLimiter downloadSpeedLimiter = - SophonDownloadSpeedLimiter.CreateInstance(LauncherConfig.DownloadSpeedLimitCached); + SophonDownloadSpeedLimiter.CreateInstance(SpeedLimiterServiceContext); // Reset status and progress properties ResetStatusAndProgress(); @@ -472,9 +472,6 @@ await Task.Run(() => SophonLogger.LogHandler -= UpdateSophonLogHandler; } httpClient.Dispose(); - - // Unsubscribe download limiter - LauncherConfig.DownloadSpeedLimitChanged -= downloadSpeedLimiter.GetListener(); } } } @@ -718,7 +715,7 @@ await GameVersionManager.GamePreset // Create a sophon download speed limiter instance SophonDownloadSpeedLimiter downloadSpeedLimiter = - SophonDownloadSpeedLimiter.CreateInstance(LauncherConfig.DownloadSpeedLimitCached); + SophonDownloadSpeedLimiter.CreateInstance(SpeedLimiterServiceContext); // Add base game diff data bool isSuccess = await AddSophonDiffAssetsToList( diff --git a/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.SophonPatch.cs b/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.SophonPatch.cs index b4a88c6503..1c12c0dc09 100644 --- a/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.SophonPatch.cs +++ b/CollapseLauncher/Classes/InstallManagement/Base/InstallManagerBase.SophonPatch.cs @@ -31,6 +31,7 @@ using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; +#pragma warning disable IDE0130 #nullable enable namespace CollapseLauncher.InstallManager.Base @@ -113,7 +114,7 @@ await SophonPatch.CreateSophonChunkManifestInfoPair(httpClient, // Create a sophon download speed limiter instance SophonDownloadSpeedLimiter downloadSpeedLimiter = - SophonDownloadSpeedLimiter.CreateInstance(LauncherConfig.DownloadSpeedLimitCached); + SophonDownloadSpeedLimiter.CreateInstance(SpeedLimiterServiceContext); // Get the patch assets to download (List AssetList, List InfoPairs, bool IsAllowRemoveOldFile) patchAssets = @@ -325,13 +326,13 @@ private async Task SpawnAdditionalPackageDownloadDialog(long baseDownloadS } protected virtual async Task<(List AssetList, List InfoPairs, bool IsAllowRemoveOldFile)> - GetAlterSophonPatchAssets(HttpClient httpClient, - string manifestUrl, - string downloadOverUrl, - List matchingFields, - string updateVersionfrom, + GetAlterSophonPatchAssets(HttpClient httpClient, + string manifestUrl, + string downloadOverUrl, + List matchingFields, + string updateVersionfrom, SophonDownloadSpeedLimiter downloadLimiter, - CancellationToken token) + CancellationToken token) { SophonChunkManifestInfoPair? rootPatchManifest = null; SophonChunkManifestInfoPair? rootMainManifest = null; @@ -505,7 +506,7 @@ await EnsureDiskSpaceSufficiencyAsync(downloadSizePatchOnlyRemote, } string patchFilePath = Path.Combine(patchOutputDir, asset.PatchHash); - FileInfo patchFileInfo = new FileInfo(patchFilePath); + FileInfo patchFileInfo = new(patchFilePath); if (!patchFileInfo.Exists) { diff --git a/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs b/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs index 732db006c2..1891d6f026 100644 --- a/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs +++ b/CollapseLauncher/Classes/Interfaces/Class/ProgressBase.cs @@ -166,11 +166,17 @@ public ObservableCollection AssetEntry // Extension for IGameInstallManager - private const int RefreshInterval = 100; + private const int RefreshInterval = 100; + protected nint SpeedLimiterServiceContext { get; } = SpeedLimiterService.CreateServiceContext(); public bool IsSophonInUpdateMode { get; protected set; } protected bool IsAllowExtractCorruptZip { get; set; } + ~ProgressBase() + { + SpeedLimiterService.FreeServiceContext(SpeedLimiterServiceContext); + } + #region ProgressEventHandlers - Fetch protected void _innerObject_ProgressAdapter(object? sender, TotalPerFileProgress e) => ProgressChanged?.Invoke(sender, e); @@ -1334,16 +1340,8 @@ protected virtual async Task RunDownloadTask(long assetSize, throw new InvalidOperationException("Both assetURL and secondaryURL cannot be empty! You must define one of them!"); } - // For any instances that uses Burst Download and if the speed limiter is null when - // _isBurstDownloadEnabled set to false, then create the speed limiter instance - bool isUseSelfSpeedLimiter = !IsBurstDownloadEnabled; - DownloadSpeedLimiter? downloadSpeedLimiter = null; - if (isUseSelfSpeedLimiter) - { - // Create the speed limiter instance and register the listener - downloadSpeedLimiter = DownloadSpeedLimiter.CreateInstance(LauncherConfig.DownloadSpeedLimitCached); - LauncherConfig.DownloadSpeedLimitChanged += downloadSpeedLimiter.GetListener(); - } + // Update 2026/02/22 - The download speed limiter is currently usable even on Burst Download Mode. + DownloadSpeedLimiter downloadSpeedLimiter = DownloadSpeedLimiter.CreateInstance(SpeedLimiterServiceContext); try { @@ -1370,14 +1368,6 @@ await downloadClient.DownloadAsync(assetURL, assetURL = null; goto StartOver; } - finally - { - // If the self speed listener is used, then unregister the listener - if (isUseSelfSpeedLimiter && downloadSpeedLimiter != null) - { - LauncherConfig.DownloadSpeedLimitChanged -= downloadSpeedLimiter.GetListener(); - } - } } #endregion diff --git a/CollapseLauncher/Classes/Plugins/PluginInfo.cs b/CollapseLauncher/Classes/Plugins/PluginInfo.cs index 11685726d6..da64d87d11 100644 --- a/CollapseLauncher/Classes/Plugins/PluginInfo.cs +++ b/CollapseLauncher/Classes/Plugins/PluginInfo.cs @@ -19,8 +19,10 @@ using System.Threading; using System.Threading.Tasks; using WinRT; - +using SpeedLimiterService = CollapseLauncher.Helper.SpeedLimiterService; +// ReSharper disable CheckNamespace // ReSharper disable LoopCanBeConvertedToQuery +#pragma warning disable IDE0130 namespace CollapseLauncher.Plugins; @@ -33,13 +35,6 @@ public partial class PluginInfo : INotifyPropertyChanged, IDisposable internal const string MarkPendingUpdateFileName = "_markPendingUpdate"; internal const string MarkPendingUpdateApplyFileName = "_markPendingUpdateApply"; - private unsafe delegate void DelegateGetPluginUpdateCdnList(int* count, ushort*** ptr); - private unsafe delegate GameVersion* DelegateGetPluginStandardVersion(); - private unsafe delegate GameVersion* DelegateGetPluginVersion(); - private unsafe delegate void* DelegateGetPlugin(); - private delegate void DelegateFreePlugin(); - private delegate void DelegateSetCallback(nint callbackP); - private bool _isDisposed; public event PropertyChangedEventHandler? PropertyChanged = delegate { }; @@ -241,6 +236,11 @@ public unsafe PluginInfo(string pluginFilePath, string pluginRelName, PluginMani PresetConfigs[i] = presetConfigWrapper; } + if (SpeedLimiterService.Shared.IsEnabled) + { + ToggleSpeedLimiterService(true); + } + isPluginLoaded = true; } catch @@ -300,6 +300,35 @@ internal unsafe void DisableDnsResolver() Logger.LogWriteLine($"[PluginInfo] Plugin: {Name} DNS Resolver Callbacks have been detached!", LogType.Debug, true); } + internal unsafe void ToggleSpeedLimiterService(bool isEnable) + { + if (!IsLoaded) + { + return; + } + + if (!Handle.TryGetExportUnsafe("RegisterSpeedThrottlerService", out nint callP)) + { + return; + } + + nint addOrWaitCallbackP = isEnable + ? SpeedLimiterService.AddBytesOrWaitAsyncDelegatePtr + : nint.Zero; + + nint getSharedThrottledBytesP = isEnable + ? SpeedLimiterService.GetSharedThrottleBytesDelegatePtr + : nint.Zero; + + HResult hr = ((delegate* unmanaged[Cdecl])callP)(addOrWaitCallbackP, getSharedThrottledBytesP); + if (Marshal.GetExceptionForHR(hr) is { } exception) + { + Logger.LogWriteLine($"[PluginInfo] Plugin: {Name} failed to register speed throttler service with error code: {hr} {exception}", + LogType.Error, + true); + } + } + internal async Task Initialize(CancellationToken token = default) { if (!IsLoaded) diff --git a/CollapseLauncher/CollapseLauncher.csproj b/CollapseLauncher/CollapseLauncher.csproj index a537cce560..a23eaa4a3d 100644 --- a/CollapseLauncher/CollapseLauncher.csproj +++ b/CollapseLauncher/CollapseLauncher.csproj @@ -218,6 +218,12 @@ + + + @@ -510,6 +516,11 @@ + + + diff --git a/CollapseLauncher/Lib/Hi3Helper.Throttle.dll b/CollapseLauncher/Lib/Hi3Helper.Throttle.dll new file mode 100644 index 0000000000..f4efcb7e81 Binary files /dev/null and b/CollapseLauncher/Lib/Hi3Helper.Throttle.dll differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.001 b/CollapseLauncher/StaticLib/StaticLib.7z.001 index eccfae304e..76108247cd 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.001 and b/CollapseLauncher/StaticLib/StaticLib.7z.001 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.002 b/CollapseLauncher/StaticLib/StaticLib.7z.002 index 8cb048ebbe..f52ae39835 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.002 and b/CollapseLauncher/StaticLib/StaticLib.7z.002 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.003 b/CollapseLauncher/StaticLib/StaticLib.7z.003 index 6ba5afabe4..57123e36a5 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.003 and b/CollapseLauncher/StaticLib/StaticLib.7z.003 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.004 b/CollapseLauncher/StaticLib/StaticLib.7z.004 index d011a1ab71..43bdc75484 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.004 and b/CollapseLauncher/StaticLib/StaticLib.7z.004 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.005 b/CollapseLauncher/StaticLib/StaticLib.7z.005 index 5607f231a9..91c469a0eb 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.005 and b/CollapseLauncher/StaticLib/StaticLib.7z.005 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.006 b/CollapseLauncher/StaticLib/StaticLib.7z.006 index c04be25da5..b4f031fe5d 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.006 and b/CollapseLauncher/StaticLib/StaticLib.7z.006 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.007 b/CollapseLauncher/StaticLib/StaticLib.7z.007 index df0dddeb7b..d4756d9194 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.007 and b/CollapseLauncher/StaticLib/StaticLib.7z.007 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.008 b/CollapseLauncher/StaticLib/StaticLib.7z.008 index dbbe2b3518..9b4a48dd15 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.008 and b/CollapseLauncher/StaticLib/StaticLib.7z.008 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.009 b/CollapseLauncher/StaticLib/StaticLib.7z.009 index ae0e0a376a..5c4332ed47 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.009 and b/CollapseLauncher/StaticLib/StaticLib.7z.009 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.010 b/CollapseLauncher/StaticLib/StaticLib.7z.010 index b5c8853197..ab41cd5b9c 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.010 and b/CollapseLauncher/StaticLib/StaticLib.7z.010 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.011 b/CollapseLauncher/StaticLib/StaticLib.7z.011 index 66a6be99e2..e92d0169c8 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.011 and b/CollapseLauncher/StaticLib/StaticLib.7z.011 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.012 b/CollapseLauncher/StaticLib/StaticLib.7z.012 index cd16f41eb0..3ebcf29c65 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.012 and b/CollapseLauncher/StaticLib/StaticLib.7z.012 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.013 b/CollapseLauncher/StaticLib/StaticLib.7z.013 index 3126b13d64..6a2e871900 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.013 and b/CollapseLauncher/StaticLib/StaticLib.7z.013 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.014 b/CollapseLauncher/StaticLib/StaticLib.7z.014 index 69ad74555b..b580820bf4 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.014 and b/CollapseLauncher/StaticLib/StaticLib.7z.014 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.015 b/CollapseLauncher/StaticLib/StaticLib.7z.015 index d943e33550..90dc7f8a78 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.015 and b/CollapseLauncher/StaticLib/StaticLib.7z.015 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.016 b/CollapseLauncher/StaticLib/StaticLib.7z.016 index f46683b92d..500361c732 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.016 and b/CollapseLauncher/StaticLib/StaticLib.7z.016 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.017 b/CollapseLauncher/StaticLib/StaticLib.7z.017 index cfb5a9c9f7..d1013edbbd 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.017 and b/CollapseLauncher/StaticLib/StaticLib.7z.017 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.018 b/CollapseLauncher/StaticLib/StaticLib.7z.018 index ec86722a98..7e3227a80a 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.018 and b/CollapseLauncher/StaticLib/StaticLib.7z.018 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.019 b/CollapseLauncher/StaticLib/StaticLib.7z.019 index d4ca510122..6d8f76c745 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.019 and b/CollapseLauncher/StaticLib/StaticLib.7z.019 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.020 b/CollapseLauncher/StaticLib/StaticLib.7z.020 index 6065de9be9..51f1d0e680 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.020 and b/CollapseLauncher/StaticLib/StaticLib.7z.020 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.021 b/CollapseLauncher/StaticLib/StaticLib.7z.021 index ec2a1fd017..3a9170c8df 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.021 and b/CollapseLauncher/StaticLib/StaticLib.7z.021 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.022 b/CollapseLauncher/StaticLib/StaticLib.7z.022 index 71617f75f9..df0ca3c589 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.022 and b/CollapseLauncher/StaticLib/StaticLib.7z.022 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.023 b/CollapseLauncher/StaticLib/StaticLib.7z.023 index d0106d5f32..ebfccacd0e 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.023 and b/CollapseLauncher/StaticLib/StaticLib.7z.023 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.024 b/CollapseLauncher/StaticLib/StaticLib.7z.024 index a2ec087070..316899b754 100644 Binary files a/CollapseLauncher/StaticLib/StaticLib.7z.024 and b/CollapseLauncher/StaticLib/StaticLib.7z.024 differ diff --git a/CollapseLauncher/StaticLib/StaticLib.7z.025 b/CollapseLauncher/StaticLib/StaticLib.7z.025 new file mode 100644 index 0000000000..34d674e0f9 Binary files /dev/null and b/CollapseLauncher/StaticLib/StaticLib.7z.025 differ diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml index 51e9e7b2f1..07a60b79ec 100644 --- a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml +++ b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml @@ -4,6 +4,7 @@ xmlns:conv="using:CollapseLauncher.Pages" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:helper="using:Hi3Helper" + xmlns:extHelper="using:CollapseLauncher.Helper" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" CacheMode="BitmapCache" Loaded="Control_Loaded" @@ -94,13 +95,15 @@ Style="{ThemeResource SubtitleTextBlockStyle}" Text="{x:Bind helper:Locale.Lang._SettingsPage.FileDownloadSettings_Title}" /> + ColumnSpacing="8" + DataContext="{x:Bind extHelper:SpeedLimiterService.Shared}"> @@ -110,7 +113,7 @@ MinWidth="120" MaxWidth="300" Header="{x:Bind helper:Locale.Lang._SettingsPage.FileDownloadSettings_SpeedLimit_NumBox}" - IsEnabled="{x:Bind NetworkDownloadSpeedLimitToggle.IsOn, Mode=OneWay}" + IsEnabled="{Binding ElementName=NetworkDownloadSpeedLimitToggle, Path=IsOn, Mode=OneWay}" LargeChange="10" Maximum="1000" Minimum="0" @@ -118,9 +121,8 @@ SmallChange="0.125" SpinButtonPlacementMode="Inline" Text="100" - Value="{x:Bind DownloadSpeedLimit, Mode=TwoWay}" /> - + + Text="{Binding ElementName=NetworkDownloadSpeedLimitNumberBox, Path=Value, Converter={StaticResource DownloadSpeedLimitToStringConverter}, Mode=OneWay}" /> diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml.cs b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml.cs index aae6ad74fb..e46399f657 100644 --- a/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml.cs +++ b/CollapseLauncher/XAMLs/MainApp/Pages/Dialogs/DownloadSettings.xaml.cs @@ -2,7 +2,6 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; -using System; namespace CollapseLauncher.Dialogs { @@ -20,43 +19,6 @@ private int PostInstallShutdownTimeout } #endregion - #region Download Speed Limiter Properties - private bool IsUseDownloadSpeedLimiter - { - get - { - bool value = LauncherConfig.IsUseDownloadSpeedLimiter; - NetworkDownloadSpeedLimitGrid.Opacity = value ? 1 : 0.45; - if (value) - LauncherConfig.IsBurstDownloadModeEnabled = false; - return value; - } - set - { - NetworkDownloadSpeedLimitGrid.Opacity = value ? 1 : 0.45; - if (value) - LauncherConfig.IsBurstDownloadModeEnabled = false; - LauncherConfig.IsUseDownloadSpeedLimiter = value; - } - } - - private double DownloadSpeedLimit - { - get - { - double val = LauncherConfig.DownloadSpeedLimit; - double valDividedM = val / (1 << 20); - return valDividedM; - } - set - { - long valBfromM = (long)(value * (1 << 20)); - - LauncherConfig.DownloadSpeedLimit = Math.Max(valBfromM, 0); - } - } - #endregion - internal DownloadSettings(GamePresetProperty currentGameProperty) { CurrentGameProperty = currentGameProperty; diff --git a/CollapseLauncher/XAMLs/MainApp/Pages/SettingsPage.xaml b/CollapseLauncher/XAMLs/MainApp/Pages/SettingsPage.xaml index a328f9bc13..7b065c29fd 100644 --- a/CollapseLauncher/XAMLs/MainApp/Pages/SettingsPage.xaml +++ b/CollapseLauncher/XAMLs/MainApp/Pages/SettingsPage.xaml @@ -9,6 +9,7 @@ xmlns:conv="using:CollapseLauncher.Pages" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ext="using:CollapseLauncher.Extension" + xmlns:extHelper="using:CollapseLauncher.Helper" xmlns:helper="using:Hi3Helper" xmlns:innerConfig="using:Hi3Helper.Shared.Region" xmlns:backgroundManager="using:CollapseLauncher.GameManagement.ImageBackground" @@ -1248,10 +1249,12 @@ + @@ -1333,11 +1336,13 @@ @@ -1348,7 +1353,7 @@ MinWidth="120" MaxWidth="300" Header="{x:Bind helper:Locale.Lang._SettingsPage.FileDownloadSettings_SpeedLimit_NumBox}" - IsEnabled="{x:Bind NetworkDownloadSpeedLimitToggle.IsOn, Mode=OneWay}" + IsEnabled="{Binding ElementName=NetworkDownloadSpeedLimitToggle, Path=IsOn, Mode=OneWay}" LargeChange="10" Maximum="1000" Minimum="0" @@ -1356,7 +1361,7 @@ SmallChange="0.125" SpinButtonPlacementMode="Inline" Text="100" - Value="{x:Bind DownloadSpeedLimit, Mode=TwoWay}" /> + Value="{Binding CurrentThrottleMebiBytes, Mode=TwoWay}" /> LauncherConfig.IsBurstDownloadModeEnabled = value; } - private bool IsUseDownloadSpeedLimiter - { - get - { - bool value = LauncherConfig.IsUseDownloadSpeedLimiter; - if (value) - NetworkBurstDownloadModeToggle.IsOn = false; - NetworkBurstDownloadModeToggle.IsEnabled = !value; - return value; - } - set - { - if (value) - NetworkBurstDownloadModeToggle.IsOn = false; - NetworkBurstDownloadModeToggle.IsEnabled = !value; - LauncherConfig.IsUseDownloadSpeedLimiter = value; - } - } - private bool IsUsePreallocatedDownloader { get @@ -1346,22 +1327,6 @@ private bool IsEnforceToUse7ZipOnExtract set => IsEnforceToUse7zipOnExtract = value; } - private double DownloadSpeedLimit - { - get - { - double val = LauncherConfig.DownloadSpeedLimit; - double valDividedM = val / (1 << 20); - return valDividedM; - } - set - { - long valBfromM = (long)(value * (1 << 20)); - - LauncherConfig.DownloadSpeedLimit = Math.Max(valBfromM, 0); - } - } - private double DownloadChunkSize { get diff --git a/Hi3Helper.Core/Classes/Shared/Region/LauncherConfig.cs b/Hi3Helper.Core/Classes/Shared/Region/LauncherConfig.cs index 7ed8c9e66e..04baf889c5 100644 --- a/Hi3Helper.Core/Classes/Shared/Region/LauncherConfig.cs +++ b/Hi3Helper.Core/Classes/Shared/Region/LauncherConfig.cs @@ -471,15 +471,14 @@ public static bool IsUseDownloadSpeedLimiter set { SetAndSaveConfigValue("IsUseDownloadSpeedLimiter", value); - _ = DownloadSpeedLimit; } } public static long DownloadSpeedLimit { - get => DownloadSpeedLimitCached = GetAppConfigValue("DownloadSpeedLimit"); - set => SetAndSaveConfigValue("DownloadSpeedLimit", DownloadSpeedLimitCached = value); + get => GetAppConfigValue("DownloadSpeedLimit"); + set => SetAndSaveConfigValue("DownloadSpeedLimit", value); } public static int DownloadChunkSize @@ -505,19 +504,7 @@ public static bool IsEnforceToUse7zipOnExtract set => SetAndSaveConfigValue("EnforceToUse7zipOnExtract", value); } - public static long DownloadSpeedLimitCached - { - get; - set - { - field = IsUseDownloadSpeedLimiter ? value : 0; - DownloadSpeedLimitChanged?.Invoke(null, field); - } - } - - public static event EventHandler? DownloadSpeedLimitChanged; - - private static bool? _cachedIsInstantRegionChange = null; + private static bool? _cachedIsInstantRegionChange; public static bool IsInstantRegionChange { diff --git a/Hi3Helper.Core/Lang/en_US.json b/Hi3Helper.Core/Lang/en_US.json index ea5bd61c20..0b2bfd6eb5 100644 --- a/Hi3Helper.Core/Lang/en_US.json +++ b/Hi3Helper.Core/Lang/en_US.json @@ -690,8 +690,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Default:", "FileDownloadSettings_SpeedLimitHelp2": "Speed Limit value range:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading. This setting cannot be used alongside the", - "FileDownloadSettings_SpeedLimitHelp5": "setting.", + "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "New Pre-allocated Downloader", "FileDownloadSettings_NewPreallocChunk_Subtitle": "For Game Installation, Game Repair and Cache Updates only.", diff --git a/Hi3Helper.Core/Lang/es_419.json b/Hi3Helper.Core/Lang/es_419.json index 838ec795a6..00ee80b5a9 100644 --- a/Hi3Helper.Core/Lang/es_419.json +++ b/Hi3Helper.Core/Lang/es_419.json @@ -690,8 +690,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Por Defecto:", "FileDownloadSettings_SpeedLimitHelp2": "Rango límite de velocidad:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "Limita el ancho de banda máximo permitido para la descarga. Esta opción no puede utilizarse junto con la opción", - "FileDownloadSettings_SpeedLimitHelp5": ".", + "FileDownloadSettings_SpeedLimitHelp4": "Limita el ancho de banda máximo permitido para la descarga.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "Nuevo Descargador Pre-asignado", "FileDownloadSettings_NewPreallocChunk_Subtitle": "Solo para la Instalación, Reparación y actualización de Caché del juego.", diff --git a/Hi3Helper.Core/Lang/fr_FR.json b/Hi3Helper.Core/Lang/fr_FR.json index 47021f1c10..6e7e0ab704 100644 --- a/Hi3Helper.Core/Lang/fr_FR.json +++ b/Hi3Helper.Core/Lang/fr_FR.json @@ -651,8 +651,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Valeur par défaut :", "FileDownloadSettings_SpeedLimitHelp2": "Plage de valeurs :", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 Mio/s", - "FileDownloadSettings_SpeedLimitHelp4": "Limite l'utilisation maximale de la bande passante pour le téléchargement. Le paramètre «", - "FileDownloadSettings_SpeedLimitHelp5": "» ne peut être utilisé si la limitation de bande passante est activée.", + "FileDownloadSettings_SpeedLimitHelp4": "Limite l'utilisation maximale de la bande passante pour le téléchargement.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "Nouveau téléchargeur avec préallocation", "FileDownloadSettings_NewPreallocChunk_Subtitle": "Uniquement pour l'installation, la réparation et la mise à jour des caches du jeu.", diff --git a/Hi3Helper.Core/Lang/id_ID.json b/Hi3Helper.Core/Lang/id_ID.json index 7555d1b992..2ebea7f869 100644 --- a/Hi3Helper.Core/Lang/id_ID.json +++ b/Hi3Helper.Core/Lang/id_ID.json @@ -677,8 +677,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Nilai Bawaan:", "FileDownloadSettings_SpeedLimitHelp2": "Jangkauan nilai untuk Batasan Kecepatan:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/d", - "FileDownloadSettings_SpeedLimitHelp4": "Membatasi berapa banyak maksimum bandwidth yang diperbolehkan saat mengunduh. Pengaturan", - "FileDownloadSettings_SpeedLimitHelp5": "tidak dapat digunakan apabila pengaturan Batasan Kecepatan sedang digunakan.", + "FileDownloadSettings_SpeedLimitHelp4": "Membatasi berapa banyak maksimum bandwidth yang diperbolehkan saat mengunduh.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "Gunakan Pengunduh Baru Berbasis Prealokasi", "FileDownloadSettings_NewPreallocChunk_Subtitle": "Hanya untuk Pemasangan Game, Perbaikan Game dan Pembaruan Cache.", diff --git a/Hi3Helper.Core/Lang/ja_JP.json b/Hi3Helper.Core/Lang/ja_JP.json index d974415a34..efbd6e38fd 100644 --- a/Hi3Helper.Core/Lang/ja_JP.json +++ b/Hi3Helper.Core/Lang/ja_JP.json @@ -690,8 +690,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "デフォルト:", "FileDownloadSettings_SpeedLimitHelp2": "速度制限の値の範囲:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/秒", - "FileDownloadSettings_SpeedLimitHelp4": "ダウンロードに使用できる最大帯域幅を制限します。この設定は", - "FileDownloadSettings_SpeedLimitHelp5": "と併用できません。", + "FileDownloadSettings_SpeedLimitHelp4": "ダウンロードに使用できる最大帯域幅を制限します。", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "新型事前割り当てダウンローダー", "FileDownloadSettings_NewPreallocChunk_Subtitle": "ゲームのインストール、修復、キャッシュ更新にのみ適用されます。", diff --git a/Hi3Helper.Core/Lang/ko_KR.json b/Hi3Helper.Core/Lang/ko_KR.json index 0c8e5f1624..a698743b59 100644 --- a/Hi3Helper.Core/Lang/ko_KR.json +++ b/Hi3Helper.Core/Lang/ko_KR.json @@ -648,8 +648,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "기본:", "FileDownloadSettings_SpeedLimitHelp2": "속도 제한 값의 범위:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/초", - "FileDownloadSettings_SpeedLimitHelp4": "다운로드에 사용하는 최대 대역폭을 제한해요. 이 설정은", - "FileDownloadSettings_SpeedLimitHelp5": "와 같이 사용되지 않아요.", + "FileDownloadSettings_SpeedLimitHelp4": "다운로드에 사용하는 최대 대역폭을 제한해요.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "새로운 사전 할당 다운로더", "FileDownloadSettings_NewPreallocChunk_Subtitle": "게임 설치, 게임 복구 또는 캐시 업데이트 전용.", diff --git a/Hi3Helper.Core/Lang/pt_BR.json b/Hi3Helper.Core/Lang/pt_BR.json index 9e38c8c48e..361ba5ddb2 100644 --- a/Hi3Helper.Core/Lang/pt_BR.json +++ b/Hi3Helper.Core/Lang/pt_BR.json @@ -648,8 +648,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Default:", "FileDownloadSettings_SpeedLimitHelp2": "Speed Limit value range:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading. This setting cannot be used alongside the", - "FileDownloadSettings_SpeedLimitHelp5": "setting.", + "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "New Pre-allocated Downloader", "FileDownloadSettings_NewPreallocChunk_Subtitle": "For Game Installation, Game Repair and Cache Updates only.", diff --git a/Hi3Helper.Core/Lang/ru_RU.json b/Hi3Helper.Core/Lang/ru_RU.json index 82a2d035fb..bc685238c0 100644 --- a/Hi3Helper.Core/Lang/ru_RU.json +++ b/Hi3Helper.Core/Lang/ru_RU.json @@ -648,8 +648,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Default:", "FileDownloadSettings_SpeedLimitHelp2": "Speed Limit value range:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading. This setting cannot be used alongside the", - "FileDownloadSettings_SpeedLimitHelp5": "setting.", + "FileDownloadSettings_SpeedLimitHelp4": "Limits the maximum allowed bandwidth for downloading.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "New Pre-allocated Downloader", "FileDownloadSettings_NewPreallocChunk_Subtitle": "For Game Installation, Game Repair and Cache Updates only.", diff --git a/Hi3Helper.Core/Lang/th_TH.json b/Hi3Helper.Core/Lang/th_TH.json index 471747b27a..abc9525b23 100644 --- a/Hi3Helper.Core/Lang/th_TH.json +++ b/Hi3Helper.Core/Lang/th_TH.json @@ -650,8 +650,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "ค่าเริ่มต้น:", "FileDownloadSettings_SpeedLimitHelp2": "ช่วงค่าจำกัดความเร็ว:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "จำกัดแบนด์วิดท์สูงสุดที่อนุญาตสำหรับการดาวน์โหลด การตั้งค่านี้ไม่สามารถใช้ร่วมกับ", - "FileDownloadSettings_SpeedLimitHelp5": "การตั้งค่า.", + "FileDownloadSettings_SpeedLimitHelp4": "จำกัดแบนด์วิดท์สูงสุดที่อนุญาตสำหรับการดาวน์โหลด.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "ตัวดาวน์โหลดที่จัดสรรล่วงหน้าใหม่", "FileDownloadSettings_NewPreallocChunk_Subtitle": "สำหรับการติดตั้งเกม, ซ่อมแซมเกม และอัปเดตแคชเท่านั้น", diff --git a/Hi3Helper.Core/Lang/uk_UA.json b/Hi3Helper.Core/Lang/uk_UA.json index dde7106ec0..395bfe36c1 100644 --- a/Hi3Helper.Core/Lang/uk_UA.json +++ b/Hi3Helper.Core/Lang/uk_UA.json @@ -648,8 +648,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "За замовчуванням: ", "FileDownloadSettings_SpeedLimitHelp2": "Діапазон значень обмеження швидкості:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 МіБ/с", - "FileDownloadSettings_SpeedLimitHelp4": "Обмежує максимальну дозволену пропускну здатність для завантаження. Це налаштування не можна використовувати разом з", - "FileDownloadSettings_SpeedLimitHelp5": "Налаштування.", + "FileDownloadSettings_SpeedLimitHelp4": "Обмежує максимальну дозволену пропускну здатність для завантаження.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "Новий попередньо виділений завантажувач", "FileDownloadSettings_NewPreallocChunk_Subtitle": "Тільки для встановлення гри, ремонту гри та оновлень кешу.", diff --git a/Hi3Helper.Core/Lang/vi_VN.json b/Hi3Helper.Core/Lang/vi_VN.json index 4154aeac3b..f7162a2396 100644 --- a/Hi3Helper.Core/Lang/vi_VN.json +++ b/Hi3Helper.Core/Lang/vi_VN.json @@ -651,8 +651,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "Mặc định:", "FileDownloadSettings_SpeedLimitHelp2": "Khoảng giới hạn có thể nhập:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "Giới hạn băng thông tối đa sử dụng khi tải xuống. Cài đặt này không thể dùng chung với ", - "FileDownloadSettings_SpeedLimitHelp5": ".", + "FileDownloadSettings_SpeedLimitHelp4": "Giới hạn băng thông tối đa sử dụng khi tải xuống.", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "Tải xuống phân bổ sẵn dung lượng", "FileDownloadSettings_NewPreallocChunk_Subtitle": "Chỉ cho cài đặt game, sửa game và cập nhật cache.", diff --git a/Hi3Helper.Core/Lang/zh_CN.json b/Hi3Helper.Core/Lang/zh_CN.json index d16c2054d3..0952dfc577 100644 --- a/Hi3Helper.Core/Lang/zh_CN.json +++ b/Hi3Helper.Core/Lang/zh_CN.json @@ -690,8 +690,8 @@ "FileDownloadSettings_SpeedLimitHelp1": "默认:", "FileDownloadSettings_SpeedLimitHelp2": "速度限制取值范围:", "FileDownloadSettings_SpeedLimitHelp3": "1 - 1000 MiB/s", - "FileDownloadSettings_SpeedLimitHelp4": "限制允许的最大下载带宽。该设置不能与", - "FileDownloadSettings_SpeedLimitHelp5": "同时使用。", + "FileDownloadSettings_SpeedLimitHelp4": "限制允许的最大下载带宽。", + "FileDownloadSettings_SpeedLimitHelp5": "", "FileDownloadSettings_NewPreallocChunk_Title": "预分配下载器(新)", "FileDownloadSettings_NewPreallocChunk_Subtitle": "仅适用于游戏安装、游戏修复与缓存更新。", diff --git a/Hi3Helper.Http b/Hi3Helper.Http index 0a583588c8..09d5cdb1ed 160000 --- a/Hi3Helper.Http +++ b/Hi3Helper.Http @@ -1 +1 @@ -Subproject commit 0a583588c860b038f1ca766e3e4b24a4305e4b11 +Subproject commit 09d5cdb1edeb7809e00bdc8f916e6581b460d58f diff --git a/Hi3Helper.Plugin.Core b/Hi3Helper.Plugin.Core index 55358d4800..5213d3082a 160000 --- a/Hi3Helper.Plugin.Core +++ b/Hi3Helper.Plugin.Core @@ -1 +1 @@ -Subproject commit 55358d4800a8c703615b19949d96acdec0357889 +Subproject commit 5213d3082a166609ac32c0811a1c4c40ccd11059 diff --git a/Hi3Helper.Sophon b/Hi3Helper.Sophon index 97d81c013c..e7058e81d7 160000 --- a/Hi3Helper.Sophon +++ b/Hi3Helper.Sophon @@ -1 +1 @@ -Subproject commit 97d81c013c8ea2a7512ed8d47419c4205f40b92c +Subproject commit e7058e81d7a126aac4c7c3d95f5c28a48758ff98