mirror of
https://git.zaroz.cloud/nintendo-back-up/Ryujinx.git
synced 2025-12-16 15:32:41 +00:00
Compare commits
1 Commits
1.1.1102
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00a86f8fc2 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -79,21 +79,21 @@ jobs:
|
|||||||
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
|
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx artifact
|
- name: Upload Ryujinx artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish
|
path: publish
|
||||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish_sdl2_headless
|
path: publish_sdl2_headless
|
||||||
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Ava artifact
|
- name: Upload Ryujinx.Ava artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
|
||||||
path: publish_ava
|
path: publish_ava
|
||||||
@@ -144,14 +144,14 @@ jobs:
|
|||||||
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
|
||||||
|
|
||||||
- name: Upload Ryujinx.Ava artifact
|
- name: Upload Ryujinx.Ava artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||||
path: "publish_ava/*.tar.gz"
|
path: "publish_ava/*.tar.gz"
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
|
|
||||||
- name: Upload Ryujinx.Headless.SDL2 artifact
|
- name: Upload Ryujinx.Headless.SDL2 artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
|
||||||
path: "publish_headless/*.tar.gz"
|
path: "publish_headless/*.tar.gz"
|
||||||
|
|||||||
2
.github/workflows/checks.yml
vendored
2
.github/workflows/checks.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload report
|
- name: Upload report
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: dotnet-format
|
name: dotnet-format
|
||||||
path: ./*-report.json
|
path: ./*-report.json
|
||||||
|
|||||||
2
.github/workflows/nightly_pr_comment.yml
vendored
2
.github/workflows/nightly_pr_comment.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/github-script@v6
|
- uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const {owner, repo} = context.repo;
|
const {owner, repo} = context.repo;
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Create tag
|
- name: Create tag
|
||||||
uses: actions/github-script@v6
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
github.rest.git.createRef({
|
github.rest.git.createRef({
|
||||||
|
|||||||
40
src/Ryujinx.Ava/UI/Models/CheatModel.cs
Normal file
40
src/Ryujinx.Ava/UI/Models/CheatModel.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Models
|
||||||
|
{
|
||||||
|
public class CheatModel : BaseModel
|
||||||
|
{
|
||||||
|
private bool _isEnabled;
|
||||||
|
|
||||||
|
public event EventHandler<bool> EnableToggled;
|
||||||
|
|
||||||
|
public CheatModel(string name, string buildId, bool isEnabled)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
BuildId = buildId;
|
||||||
|
IsEnabled = isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEnabled
|
||||||
|
{
|
||||||
|
get => _isEnabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isEnabled = value;
|
||||||
|
|
||||||
|
EnableToggled?.Invoke(this, _isEnabled);
|
||||||
|
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildId { get; }
|
||||||
|
|
||||||
|
public string BuildIdKey => $"{BuildId}-{Name}";
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string CleanName => Name[1..^7];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using Ryujinx.Ava.UI.ViewModels;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Collections.Specialized;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Models
|
|
||||||
{
|
|
||||||
public class CheatNode : BaseModel
|
|
||||||
{
|
|
||||||
private bool _isEnabled = false;
|
|
||||||
public ObservableCollection<CheatNode> SubNodes { get; } = new();
|
|
||||||
public string CleanName => Name[1..^7];
|
|
||||||
public string BuildIdKey => $"{BuildId}-{Name}";
|
|
||||||
public bool IsRootNode { get; }
|
|
||||||
public string Name { get; }
|
|
||||||
public string BuildId { get; }
|
|
||||||
public string Path { get; }
|
|
||||||
public bool IsEnabled
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (SubNodes.Count > 0)
|
|
||||||
{
|
|
||||||
return SubNodes.ToList().TrueForAll(x => x.IsEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _isEnabled;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
foreach (var cheat in SubNodes)
|
|
||||||
{
|
|
||||||
cheat.IsEnabled = value;
|
|
||||||
cheat.OnPropertyChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
_isEnabled = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CheatNode(string name, string buildId, string path, bool isRootNode, bool isEnabled = false)
|
|
||||||
{
|
|
||||||
Name = name;
|
|
||||||
BuildId = buildId;
|
|
||||||
Path = path;
|
|
||||||
IsEnabled = isEnabled;
|
|
||||||
IsRootNode = isRootNode;
|
|
||||||
|
|
||||||
SubNodes.CollectionChanged += CheatsList_CollectionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
|
||||||
OnPropertyChanged(nameof(IsEnabled));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
51
src/Ryujinx.Ava/UI/Models/CheatsList.cs
Normal file
51
src/Ryujinx.Ava/UI/Models/CheatsList.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Models
|
||||||
|
{
|
||||||
|
public class CheatsList : ObservableCollection<CheatModel>
|
||||||
|
{
|
||||||
|
public CheatsList(string buildId, string path)
|
||||||
|
{
|
||||||
|
BuildId = buildId;
|
||||||
|
Path = path;
|
||||||
|
|
||||||
|
CollectionChanged += CheatsList_CollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildId { get; }
|
||||||
|
public string Path { get; }
|
||||||
|
|
||||||
|
public bool IsEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.ToList().TrueForAll(x => x.IsEnabled);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
foreach (var cheat in this)
|
||||||
|
{
|
||||||
|
cheat.IsEnabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||||
|
{
|
||||||
|
(e.NewItems[0] as CheatModel).EnableToggled += Item_EnableToggled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Item_EnableToggled(object sender, bool e)
|
||||||
|
{
|
||||||
|
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -188,61 +188,35 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
_httpClient.Dispose();
|
_httpClient.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
amiiboJson = JsonHelper.Deserialize<AmiiboJson>(json, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
amiiboJson = JsonHelper.Deserialize<AmiiboJson>(DefaultJson, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
|
|
||||||
{
|
|
||||||
bool localIsValid = false;
|
|
||||||
bool remoteIsValid = false;
|
|
||||||
AmiiboJson amiiboJson = JsonHelper.Deserialize<AmiiboJson>(DefaultJson, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
localIsValid = TryGetAmiiboJson(File.ReadAllText(_amiiboJsonPath), out amiiboJson);
|
|
||||||
|
|
||||||
if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
|
|
||||||
{
|
|
||||||
remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
if (!(localIsValid || remoteIsValid))
|
|
||||||
{
|
|
||||||
// Neither local or remote files are valid JSON, close window.
|
|
||||||
ShowInfoDialog();
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
else if (!remoteIsValid)
|
|
||||||
{
|
|
||||||
// Only the local file is valid, the local one should be used
|
|
||||||
// but the user should be warned.
|
|
||||||
ShowInfoDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return amiiboJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadContentAsync()
|
private async Task LoadContentAsync()
|
||||||
{
|
{
|
||||||
AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
|
string amiiboJsonString = DefaultJson;
|
||||||
|
|
||||||
_amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
if (File.Exists(_amiiboJsonPath))
|
||||||
|
{
|
||||||
|
amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath);
|
||||||
|
|
||||||
|
if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated))
|
||||||
|
{
|
||||||
|
amiiboJsonString = await DownloadAmiiboJson();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
amiiboJsonString = await DownloadAmiiboJson();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
|
||||||
|
|
||||||
|
ShowInfoDialog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo;
|
||||||
|
_amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
||||||
|
|
||||||
ParseAmiiboData();
|
ParseAmiiboData();
|
||||||
}
|
}
|
||||||
@@ -388,14 +362,26 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
private async Task<bool> NeedsUpdate(DateTime oldLastModified)
|
private async Task<bool> NeedsUpdate(DateTime oldLastModified)
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
try
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
{
|
||||||
return response.Content.Headers.LastModified != oldLastModified;
|
HttpResponseMessage response =
|
||||||
}
|
await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
||||||
|
|
||||||
return false;
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return response.Content.Headers.LastModified != new DateTimeOffset(oldLastModified.Ticks - (oldLastModified.Ticks % TimeSpan.TicksPerSecond), TimeSpan.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
|
||||||
|
|
||||||
|
ShowInfoDialog();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> DownloadAmiiboJson()
|
private async Task<string> DownloadAmiiboJson()
|
||||||
|
|||||||
@@ -86,16 +86,28 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
</TreeView.Styles>
|
</TreeView.Styles>
|
||||||
<TreeView.ItemTemplate>
|
<TreeView.DataTemplates>
|
||||||
<TreeDataTemplate ItemsSource="{Binding SubNodes}">
|
<TreeDataTemplate DataType="model:CheatsList" ItemsSource="{Binding}">
|
||||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||||
<CheckBox MinWidth="20" IsChecked="{Binding IsEnabled}" />
|
<CheckBox MinWidth="20" IsChecked="{Binding IsEnabled}" />
|
||||||
<TextBlock Width="150" Text="{Binding CleanName}" IsVisible="{Binding !IsRootNode}" />
|
<TextBlock Width="150" Text="{Binding BuildId}" />
|
||||||
<TextBlock Width="150" Text="{Binding BuildId}" IsVisible="{Binding IsRootNode}" />
|
<TextBlock Text="{Binding Path}" />
|
||||||
<TextBlock Text="{Binding Path}" IsVisible="{Binding IsRootNode}" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
</TreeView.ItemTemplate>
|
<DataTemplate x:DataType="model:CheatModel">
|
||||||
|
<StackPanel
|
||||||
|
Margin="0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<CheckBox
|
||||||
|
MinWidth="20"
|
||||||
|
Margin="5,0"
|
||||||
|
Padding="0"
|
||||||
|
IsChecked="{Binding IsEnabled}" />
|
||||||
|
<TextBlock VerticalAlignment="Center" Text="{Binding CleanName}" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</TreeView.DataTemplates>
|
||||||
</TreeView>
|
</TreeView>
|
||||||
</Border>
|
</Border>
|
||||||
<DockPanel
|
<DockPanel
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
private readonly string _enabledCheatsPath;
|
private readonly string _enabledCheatsPath;
|
||||||
public bool NoCheatsFound { get; }
|
public bool NoCheatsFound { get; }
|
||||||
|
|
||||||
public AvaloniaList<CheatNode> LoadedCheats { get; }
|
public AvaloniaList<CheatsList> LoadedCheats { get; }
|
||||||
|
|
||||||
public string Heading { get; }
|
public string Heading { get; }
|
||||||
public string BuildId { get; }
|
public string BuildId { get; }
|
||||||
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
||||||
{
|
{
|
||||||
LoadedCheats = new AvaloniaList<CheatNode>();
|
LoadedCheats = new AvaloniaList<CheatsList>();
|
||||||
|
|
||||||
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
|
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
|
||||||
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
|
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
|
||||||
@@ -62,7 +62,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
string currentCheatFile = string.Empty;
|
string currentCheatFile = string.Empty;
|
||||||
string buildId = string.Empty;
|
string buildId = string.Empty;
|
||||||
|
|
||||||
CheatNode currentGroup = null;
|
CheatsList currentGroup = null;
|
||||||
|
|
||||||
foreach (var cheat in mods.Cheats)
|
foreach (var cheat in mods.Cheats)
|
||||||
{
|
{
|
||||||
@@ -72,13 +72,13 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
string parentPath = currentCheatFile.Replace(titleModsPath, "");
|
string parentPath = currentCheatFile.Replace(titleModsPath, "");
|
||||||
|
|
||||||
buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
|
buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
|
||||||
currentGroup = new CheatNode("", buildId, parentPath, true);
|
currentGroup = new CheatsList(buildId, parentPath);
|
||||||
|
|
||||||
LoadedCheats.Add(currentGroup);
|
LoadedCheats.Add(currentGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
var model = new CheatNode(cheat.Name, buildId, "", false, enabled.Contains($"{buildId}-{cheat.Name}"));
|
var model = new CheatModel(cheat.Name, buildId, enabled.Contains($"{buildId}-{cheat.Name}"));
|
||||||
currentGroup?.SubNodes.Add(model);
|
currentGroup?.Add(model);
|
||||||
|
|
||||||
cheatAdded++;
|
cheatAdded++;
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
foreach (var cheats in LoadedCheats)
|
foreach (var cheats in LoadedCheats)
|
||||||
{
|
{
|
||||||
foreach (var cheat in cheats.SubNodes)
|
foreach (var cheat in cheats)
|
||||||
{
|
{
|
||||||
if (cheat.IsEnabled)
|
if (cheat.IsEnabled)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,61 +72,37 @@ namespace Ryujinx.Ui.Windows
|
|||||||
_ = LoadContentAsync();
|
_ = LoadContentAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
amiiboJson = JsonHelper.Deserialize<AmiiboJson>(json, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
amiiboJson = JsonHelper.Deserialize<AmiiboJson>(DefaultJson, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
|
|
||||||
{
|
|
||||||
bool localIsValid = false;
|
|
||||||
bool remoteIsValid = false;
|
|
||||||
AmiiboJson amiiboJson = JsonHelper.Deserialize<AmiiboJson>(DefaultJson, _serializerContext.AmiiboJson);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
localIsValid = TryGetAmiiboJson(File.ReadAllText(_amiiboJsonPath), out amiiboJson);
|
|
||||||
|
|
||||||
if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
|
|
||||||
{
|
|
||||||
remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
if (!(localIsValid || remoteIsValid))
|
|
||||||
{
|
|
||||||
// Neither local or remote files are valid JSON, close window.
|
|
||||||
ShowInfoDialog();
|
|
||||||
Close();
|
|
||||||
}
|
|
||||||
else if (!remoteIsValid)
|
|
||||||
{
|
|
||||||
// Only the local file is valid, the local one should be used
|
|
||||||
// but the user should be warned.
|
|
||||||
ShowInfoDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return amiiboJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LoadContentAsync()
|
private async Task LoadContentAsync()
|
||||||
{
|
{
|
||||||
AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
|
string amiiboJsonString = DefaultJson;
|
||||||
|
|
||||||
_amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
if (File.Exists(_amiiboJsonPath))
|
||||||
|
{
|
||||||
|
amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath);
|
||||||
|
|
||||||
|
if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated))
|
||||||
|
{
|
||||||
|
amiiboJsonString = await DownloadAmiiboJson();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
amiiboJsonString = await DownloadAmiiboJson();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
|
||||||
|
|
||||||
|
ShowInfoDialog();
|
||||||
|
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo;
|
||||||
|
_amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
|
||||||
|
|
||||||
if (LastScannedAmiiboShowAll)
|
if (LastScannedAmiiboShowAll)
|
||||||
{
|
{
|
||||||
@@ -196,14 +172,25 @@ namespace Ryujinx.Ui.Windows
|
|||||||
|
|
||||||
private async Task<bool> NeedsUpdate(DateTime oldLastModified)
|
private async Task<bool> NeedsUpdate(DateTime oldLastModified)
|
||||||
{
|
{
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
try
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
|
||||||
{
|
{
|
||||||
return response.Content.Headers.LastModified != oldLastModified;
|
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return response.Content.Headers.LastModified != new DateTimeOffset(oldLastModified.Ticks - (oldLastModified.Ticks % TimeSpan.TicksPerSecond), TimeSpan.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
|
||||||
|
|
||||||
|
ShowInfoDialog();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> DownloadAmiiboJson()
|
private async Task<string> DownloadAmiiboJson()
|
||||||
|
|||||||
Reference in New Issue
Block a user