From 227dafae53ab6bfa98e560c390b85016f836d9d7 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Sat, 18 Dec 2021 04:01:23 +0100 Subject: [PATCH 01/52] materials + skeleton fix --- CUE4Parse | 2 +- FModel/ViewModels/CUE4ParseViewModel.cs | 6 +++--- FModel/ViewModels/MapViewerViewModel.cs | 8 ++++---- FModel/Views/Resources/Resources.xaml | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 763aca66..370b35d1 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 763aca666c1782ce51287100641bc31d9fce0d41 +Subproject commit 370b35d1e0e981501d5f18c574cb55e20ac3000d diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 5c56b30b..cbf55d12 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -752,9 +752,9 @@ namespace FModel.ViewModels } else { - Log.Error("{FileName} could not be saved", savedFileName); - FLogger.AppendError(); - FLogger.AppendText($"Could not save '{savedFileName}'", Constants.WHITE, true); + Log.Warning("{FileName} could not be saved", export.Name); + FLogger.AppendWarning(); + FLogger.AppendText($"Could not save '{export.Name}'", Constants.WHITE, true); } } diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index 9153cd7b..e36b0baa 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -375,9 +375,9 @@ namespace FModel.ViewModels await _threadWorkerView.Begin(_ => { if (!Utils.TryLoadObject("FortniteGame/Content/UI/IngameMap/UIMapManagerBR.Default__UIMapManagerBR_C", out UObject mapManager) || - !mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.ReferencedTextures.Count < 1) return; + !mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.GetFirstTexture() is not UTexture2D tex) return; - _bitmaps[0][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(mapMaterial.ReferencedTextures[0] as UTexture2D), IsEnabled = true}; + _bitmaps[0][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(tex), IsEnabled = true}; _brMiniMapImage = GetImageSource(_bitmaps[0][_FIRST_BITMAP].Layer); }); } @@ -390,9 +390,9 @@ namespace FModel.ViewModels await _threadWorkerView.Begin(_ => { if (!Utils.TryLoadObject("FortniteGame/Content/UI/IngameMap/UIMapManagerPapaya.Default__UIMapManagerPapaya_C", out UObject mapManager) || - !mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.ReferencedTextures.Count < 1) return; + !mapManager.TryGetValue(out UMaterial mapMaterial, "MapMaterial") || mapMaterial.GetFirstTexture() is not UTexture2D tex) return; - _bitmaps[1][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(mapMaterial.ReferencedTextures[0] as UTexture2D), IsEnabled = true}; + _bitmaps[1][_FIRST_BITMAP] = new MapLayer{Layer = Utils.GetBitmap(tex), IsEnabled = true}; _prMiniMapImage = GetImageSource(_bitmaps[1][_FIRST_BITMAP].Layer); }); } diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index f2f6950c..d1e0dce5 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -944,7 +944,7 @@ - + @@ -953,7 +953,7 @@ - + From 1d25732fbf39747bc7e2aa813cad84e4c81c3d98 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Mon, 20 Dec 2021 20:15:08 +0100 Subject: [PATCH 02/52] manual detected games --- CUE4Parse | 2 +- FModel/Settings/UserSettings.cs | 10 ++++ FModel/ViewModels/AesManagerViewModel.cs | 27 +++++++--- FModel/ViewModels/ApplicationViewModel.cs | 7 ++- FModel/ViewModels/CUE4ParseViewModel.cs | 36 +++++++++---- .../ViewModels/CustomDirectoriesViewModel.cs | 20 +++++-- FModel/ViewModels/GameSelectorViewModel.cs | 46 ++++++++++++++++ FModel/ViewModels/SettingsViewModel.cs | 30 ++++++++--- FModel/Views/DirectorySelector.xaml | 53 ++++++++++++++++++- FModel/Views/DirectorySelector.xaml.cs | 31 ++++++++++- 10 files changed, 227 insertions(+), 35 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 370b35d1..9bf51502 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 370b35d1e0e981501d5f18c574cb55e20ac3000d +Subproject commit 9bf51502f7318ca82d289b39df15a26ef1dbce60 diff --git a/FModel/Settings/UserSettings.cs b/FModel/Settings/UserSettings.cs index 1e6f80be..13b5da83 100644 --- a/FModel/Settings/UserSettings.cs +++ b/FModel/Settings/UserSettings.cs @@ -205,6 +205,16 @@ namespace FModel.Settings set => SetProperty(ref _imageMergerMargin, value); } + // + // can't refactor to use this data layout for everything + // because it will wipe old user settings that relies on FGame + private IDictionary _manualGames = new Dictionary(); + public IDictionary ManualGames + { + get => _manualGames; + set => SetProperty(ref _manualGames, value); + } + private IDictionary _presets = new Dictionary { {FGame.Unknown, Constants._NO_PRESET_TRIGGER}, diff --git a/FModel/ViewModels/AesManagerViewModel.cs b/FModel/ViewModels/AesManagerViewModel.cs index 9a8c6f36..2defdd9e 100644 --- a/FModel/ViewModels/AesManagerViewModel.cs +++ b/FModel/ViewModels/AesManagerViewModel.cs @@ -35,14 +35,21 @@ namespace FModel.ViewModels { await _threadWorkerView.Begin(_ => { - if (!UserSettings.Default.AesKeys.TryGetValue(_cue4Parse.Game, out _keysFromSettings) || _keysFromSettings == null) + if (_cue4Parse.Game == FGame.Unknown && + UserSettings.Default.ManualGames.TryGetValue(UserSettings.Default.GameDirectory, out var settings)) { - _keysFromSettings = new AesResponse - { - MainKey = string.Empty, - DynamicKeys = null - }; + _keysFromSettings = settings.AesKeys; } + else + { + _keysFromSettings = UserSettings.Default.AesKeys[_cue4Parse.Game]; + } + + _keysFromSettings ??= new AesResponse + { + MainKey = string.Empty, + DynamicKeys = null + }; _mainKey.Key = FixKey(_keysFromSettings.MainKey); AesKeys = new FullyObservableCollection(EnumerateAesKeys()); @@ -102,7 +109,11 @@ namespace FModel.ViewModels _cue4Parse.ClearProvider(); await _cue4Parse.LoadVfs(AesKeys); - UserSettings.Default.AesKeys[_cue4Parse.Game] = _keysFromSettings; + + if (_cue4Parse.Game == FGame.Unknown) + UserSettings.Default.ManualGames[UserSettings.Default.GameDirectory].AesKeys = _keysFromSettings; + else UserSettings.Default.AesKeys[_cue4Parse.Game] = _keysFromSettings; + Log.Information("{@Json}", UserSettings.Default); } @@ -139,4 +150,4 @@ namespace FModel.ViewModels } } } -} \ No newline at end of file +} diff --git a/FModel/ViewModels/ApplicationViewModel.cs b/FModel/ViewModels/ApplicationViewModel.cs index 37b9dffb..4a4d0308 100644 --- a/FModel/ViewModels/ApplicationViewModel.cs +++ b/FModel/ViewModels/ApplicationViewModel.cs @@ -61,7 +61,10 @@ namespace FModel.ViewModels public CopyCommand CopyCommand => _copyCommand ??= new CopyCommand(this); private CopyCommand _copyCommand; - public string TitleExtra => $"{UserSettings.Default.UpdateMode} - {CUE4Parse.Game.GetDescription()} ({UserSettings.Default.OverridedGame[CUE4Parse.Game]}){(Build != EBuildKind.Release ? $" ({Build})" : "")}"; + public string TitleExtra => + $"{UserSettings.Default.UpdateMode} - {CUE4Parse.Game.GetDescription()} (" + // FModel {UpdateMode} - {FGame} ({UE}) ({Build}) + $"{(CUE4Parse.Game == FGame.Unknown && UserSettings.Default.ManualGames.TryGetValue(UserSettings.Default.GameDirectory, out var settings) ? settings.OverridedGame : UserSettings.Default.OverridedGame[CUE4Parse.Game])})" + + $"{(Build != EBuildKind.Release ? $" ({Build})" : "")}"; public LoadingModesViewModel LoadingModes { get; } public CustomDirectoriesViewModel CustomDirectories { get; } @@ -87,7 +90,7 @@ namespace FModel.ViewModels AvoidEmptyGameDirectoryAndSetEGame(false); CUE4Parse = new CUE4ParseViewModel(UserSettings.Default.GameDirectory); - CustomDirectories = new CustomDirectoriesViewModel(CUE4Parse.Game); + CustomDirectories = new CustomDirectoriesViewModel(CUE4Parse.Game, UserSettings.Default.GameDirectory); SettingsView = new SettingsViewModel(CUE4Parse.Game); AesManager = new AesManagerViewModel(CUE4Parse); MapViewer = new MapViewerViewModel(CUE4Parse); diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index cbf55d12..e7946573 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -106,15 +106,31 @@ namespace FModel.ViewModels customVersions: UserSettings.Default.OverridedCustomVersions[Game], optionOverrides: UserSettings.Default.OverridedOptions[Game]); - if (Game == FGame.StateOfDecay2) - Provider = new DefaultFileProvider(new DirectoryInfo(gameDirectory), new List - { - new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"), - new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks") - }, - SearchOption.AllDirectories, true, versions); - else - Provider = new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, true, versions); + switch (Game) + { + case FGame.StateOfDecay2: + { + Provider = new DefaultFileProvider(new DirectoryInfo(gameDirectory), new List + { + new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\Paks"), + new(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\StateOfDecay2\\Saved\\DisabledPaks") + }, + SearchOption.AllDirectories, true, versions); + break; + } + case FGame.Unknown when UserSettings.Default.ManualGames.TryGetValue(gameDirectory, out var settings): + { + versions = new VersionContainer(settings.OverridedGame, + customVersions: settings.OverridedCustomVersions, + optionOverrides: settings.OverridedOptions); + goto default; + } + default: + { + Provider = new DefaultFileProvider(gameDirectory, SearchOption.AllDirectories, true, versions); + break; + } + } break; } @@ -248,7 +264,7 @@ namespace FModel.ViewModels file.FileCount = vfs.FileCount; } - Game = Provider.GameName.ToEnum(Game); + // Game = Provider.GameName.ToEnum(Game); }); } diff --git a/FModel/ViewModels/CustomDirectoriesViewModel.cs b/FModel/ViewModels/CustomDirectoriesViewModel.cs index 567001c7..851fd8e4 100644 --- a/FModel/ViewModels/CustomDirectoriesViewModel.cs +++ b/FModel/ViewModels/CustomDirectoriesViewModel.cs @@ -55,10 +55,12 @@ namespace FModel.ViewModels public ReadOnlyObservableCollection Directories { get; } private readonly FGame _game; + private readonly string _gameDirectoryAtLaunch; - public CustomDirectoriesViewModel(FGame game) + public CustomDirectoriesViewModel(FGame game, string directory) { _game = game; + _gameDirectoryAtLaunch = directory; _directories = new ObservableCollection(EnumerateDirectories()); Directories = new ReadOnlyObservableCollection(_directories); } @@ -89,12 +91,15 @@ namespace FModel.ViewModels public void Save() { - UserSettings.Default.CustomDirectories[_game] = new List(); + var cd = new List(); for (var i = 2; i < _directories.Count; i++) { if (_directories[i] is not MenuItem m) continue; - UserSettings.Default.CustomDirectories[_game].Add(new CustomDirectory(m.Header.ToString(), m.Tag.ToString())); + cd.Add(new CustomDirectory(m.Header.ToString(), m.Tag.ToString())); } + + if (_game == FGame.Unknown) UserSettings.Default.ManualGames[_gameDirectoryAtLaunch].CustomDirectories = cd; + else UserSettings.Default.CustomDirectories[_game] = cd; } private IEnumerable EnumerateDirectories() @@ -109,7 +114,12 @@ namespace FModel.ViewModels }; yield return new Separator(); - foreach (var setting in UserSettings.Default.CustomDirectories[_game]) + IList cd; + if (_game == FGame.Unknown && UserSettings.Default.ManualGames.TryGetValue(_gameDirectoryAtLaunch, out var settings)) + cd = settings.CustomDirectories; + else cd = UserSettings.Default.CustomDirectories[_game]; + + foreach (var setting in cd) { if (setting.DirectoryPath.EndsWith('/')) setting.DirectoryPath = setting.DirectoryPath[..^1]; @@ -157,4 +167,4 @@ namespace FModel.ViewModels }; } } -} \ No newline at end of file +} diff --git a/FModel/ViewModels/GameSelectorViewModel.cs b/FModel/ViewModels/GameSelectorViewModel.cs index fbf968df..dd0eb7dc 100644 --- a/FModel/ViewModels/GameSelectorViewModel.cs +++ b/FModel/ViewModels/GameSelectorViewModel.cs @@ -8,6 +8,10 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using CUE4Parse.UE4.Objects.Core.Serialization; +using CUE4Parse.UE4.Versions; +using FModel.Settings; +using FModel.ViewModels.ApiEndpoints.Models; using Microsoft.Win32; namespace FModel.ViewModels @@ -18,6 +22,14 @@ namespace FModel.ViewModels { public string GameName { get; set; } public string GameDirectory { get; set; } + public bool IsManual { get; set; } + + // the followings are only used when game is manually added + public AesResponse AesKeys { get; set; } + public EGame OverridedGame { get; set; } + public List OverridedCustomVersions { get; set; } + public Dictionary OverridedOptions { get; set; } + public IList CustomDirectories { get; set; } } private DetectedGame _selectedDetectedGame; @@ -33,6 +45,11 @@ namespace FModel.ViewModels public GameSelectorViewModel(string gameDirectory) { _autoDetectedGames = new ObservableCollection(EnumerateDetectedGames().Where(x => x != null)); + foreach (var game in UserSettings.Default.ManualGames.Values) + { + _autoDetectedGames.Add(game); + } + AutoDetectedGames = new ReadOnlyObservableCollection(_autoDetectedGames); if (AutoDetectedGames.FirstOrDefault(x => x.GameDirectory == gameDirectory) is { } detectedGame) @@ -43,12 +60,41 @@ namespace FModel.ViewModels SelectedDetectedGame = AutoDetectedGames.FirstOrDefault(); } + /// + /// dedicated to manual games + /// + public void AddUnknownGame(string gameName, string gameDirectory) + { + var game = new DetectedGame + { + GameName = gameName, + GameDirectory = gameDirectory, + IsManual = true, + AesKeys = null, + OverridedGame = EGame.GAME_UE4_LATEST, + OverridedCustomVersions = null, + OverridedOptions = null, + CustomDirectories = new List() + }; + + UserSettings.Default.ManualGames[gameDirectory] = game; + _autoDetectedGames.Add(game); + SelectedDetectedGame = AutoDetectedGames.Last(); + } + public void AddUnknownGame(string gameDirectory) { _autoDetectedGames.Add(new DetectedGame { GameName = gameDirectory.SubstringAfterLast('\\'), GameDirectory = gameDirectory }); SelectedDetectedGame = AutoDetectedGames.Last(); } + public void DeleteSelectedGame() + { + UserSettings.Default.ManualGames.Remove(SelectedDetectedGame.GameDirectory); // should not be a problem + _autoDetectedGames.Remove(SelectedDetectedGame); + SelectedDetectedGame = AutoDetectedGames.Last(); + } + private IEnumerable EnumerateDetectedGames() { yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks"); diff --git a/FModel/ViewModels/SettingsViewModel.cs b/FModel/ViewModels/SettingsViewModel.cs index 7c1a5922..1ebe1ef5 100644 --- a/FModel/ViewModels/SettingsViewModel.cs +++ b/FModel/ViewModels/SettingsViewModel.cs @@ -159,9 +159,18 @@ namespace FModel.ViewModels _gameSnapshot = UserSettings.Default.GameDirectory; _updateModeSnapshot = UserSettings.Default.UpdateMode; _presetSnapshot = UserSettings.Default.Presets[_game]; - _ueGameSnapshot = UserSettings.Default.OverridedGame[_game]; - _customVersionsSnapshot = UserSettings.Default.OverridedCustomVersions[_game]; - _optionsSnapshot = UserSettings.Default.OverridedOptions[_game]; + if (_game == FGame.Unknown && UserSettings.Default.ManualGames.TryGetValue(_gameSnapshot, out var settings)) + { + _ueGameSnapshot = settings.OverridedGame; + _customVersionsSnapshot = settings.OverridedCustomVersions; + _optionsSnapshot = settings.OverridedOptions; + } + else + { + _ueGameSnapshot = UserSettings.Default.OverridedGame[_game]; + _customVersionsSnapshot = UserSettings.Default.OverridedCustomVersions[_game]; + _optionsSnapshot = UserSettings.Default.OverridedOptions[_game]; + } _assetLanguageSnapshot = UserSettings.Default.AssetLanguage; _compressedAudioSnapshot = UserSettings.Default.CompressedAudioMode; _cosmeticStyleSnapshot = UserSettings.Default.CosmeticStyle; @@ -255,9 +264,18 @@ namespace FModel.ViewModels UserSettings.Default.UpdateMode = SelectedUpdateMode; UserSettings.Default.Presets[_game] = SelectedPreset; - UserSettings.Default.OverridedGame[_game] = SelectedUeGame; - UserSettings.Default.OverridedCustomVersions[_game] = SelectedCustomVersions; - UserSettings.Default.OverridedOptions[_game] = SelectedOptions; + if (_game == FGame.Unknown) + { + UserSettings.Default.ManualGames[UserSettings.Default.GameDirectory].OverridedGame = SelectedUeGame; + UserSettings.Default.ManualGames[UserSettings.Default.GameDirectory].OverridedCustomVersions = SelectedCustomVersions; + UserSettings.Default.ManualGames[UserSettings.Default.GameDirectory].OverridedOptions = SelectedOptions; + } + else + { + UserSettings.Default.OverridedGame[_game] = SelectedUeGame; + UserSettings.Default.OverridedCustomVersions[_game] = SelectedCustomVersions; + UserSettings.Default.OverridedOptions[_game] = SelectedOptions; + } UserSettings.Default.AssetLanguage = SelectedAssetLanguage; UserSettings.Default.CompressedAudioMode = SelectedCompressedAudio; UserSettings.Default.CosmeticStyle = SelectedCosmeticStyle; diff --git a/FModel/Views/DirectorySelector.xaml b/FModel/Views/DirectorySelector.xaml index 933006ae..97517abe 100644 --- a/FModel/Views/DirectorySelector.xaml +++ b/FModel/Views/DirectorySelector.xaml @@ -30,7 +30,7 @@ + Text="We like to make things as simple as possible. Choose between the detected games or manually add your own. FModel will use this information to automatically find archives to load and decrypt if needed. Make sure to not skip this step!" /> - + @@ -62,6 +62,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FModel/Views/DirectorySelector.xaml.cs b/FModel/Views/DirectorySelector.xaml.cs index 76b5b26e..4103d16e 100644 --- a/FModel/Views/DirectorySelector.xaml.cs +++ b/FModel/Views/DirectorySelector.xaml.cs @@ -32,5 +32,34 @@ namespace FModel.Views gameLauncherViewModel.AddUnknownGame(folderBrowser.SelectedPath); } } + + private void OnBrowseManualDirectories(object sender, RoutedEventArgs e) + { + var folderBrowser = new VistaFolderBrowserDialog {ShowNewFolderButton = false}; + if (folderBrowser.ShowDialog() == true) + { + HelloGameMyNameIsDirectory.Text = folderBrowser.SelectedPath; + } + } + + private void OnAddDirectory(object sender, RoutedEventArgs e) + { + if (DataContext is not GameSelectorViewModel gameLauncherViewModel|| + string.IsNullOrEmpty(HelloMyNameIsGame.Text) || + string.IsNullOrEmpty(HelloGameMyNameIsDirectory.Text)) + return; + + gameLauncherViewModel.AddUnknownGame(HelloMyNameIsGame.Text, HelloGameMyNameIsDirectory.Text); + HelloMyNameIsGame.Clear(); + HelloGameMyNameIsDirectory.Clear(); + } + + private void OnDeleteDirectory(object sender, RoutedEventArgs e) + { + if (DataContext is not GameSelectorViewModel gameLauncherViewModel) + return; + + gameLauncherViewModel.DeleteSelectedGame(); + } } -} \ No newline at end of file +} From ec71fc4491a6a94e36a8a1b74fb51ec749a1c249 Mon Sep 17 00:00:00 2001 From: iAmAsval Date: Tue, 21 Dec 2021 00:01:03 +0100 Subject: [PATCH 03/52] expander --- CUE4Parse | 2 +- FModel/MainWindow.xaml | 3 +- FModel/Views/DirectorySelector.xaml | 76 +++++++++++++-------------- FModel/Views/Resources/Resources.xaml | 3 +- 4 files changed, 40 insertions(+), 44 deletions(-) diff --git a/CUE4Parse b/CUE4Parse index 9bf51502..ba385196 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 9bf51502f7318ca82d289b39df15a26ef1dbce60 +Subproject commit ba385196acee4cb1a716a3ee69b82165ce799dcd diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml index fa5b7b35..065dbf01 100644 --- a/FModel/MainWindow.xaml +++ b/FModel/MainWindow.xaml @@ -663,7 +663,8 @@ - + diff --git a/FModel/Views/DirectorySelector.xaml b/FModel/Views/DirectorySelector.xaml index 97517abe..25a3f145 100644 --- a/FModel/Views/DirectorySelector.xaml +++ b/FModel/Views/DirectorySelector.xaml @@ -58,21 +58,15 @@ + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + - - - - + + + + + diff --git a/FModel/Views/Resources/Resources.xaml b/FModel/Views/Resources/Resources.xaml index d1e0dce5..4de03962 100644 --- a/FModel/Views/Resources/Resources.xaml +++ b/FModel/Views/Resources/Resources.xaml @@ -1286,7 +1286,6 @@ - - @@ -190,11 +226,11 @@ - - -