diff --git a/CUE4Parse b/CUE4Parse index 2d5e2bdd..2cdf9d61 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 2d5e2bdd35db42759d8320076778737fcf9d53a2 +Subproject commit 2cdf9d61e66253f746f6a6e5b23b57979fbaab69 diff --git a/FModel/Creator/Bases/FN/BaseBundle.cs b/FModel/Creator/Bases/FN/BaseBundle.cs index a8b4f782..ea5114e8 100644 --- a/FModel/Creator/Bases/FN/BaseBundle.cs +++ b/FModel/Creator/Bases/FN/BaseBundle.cs @@ -124,8 +124,7 @@ public class BaseBundle : UCreator } var shaper = new CustomSKShaper(_headerPaint.Typeface); - var shapedText = shaper.Shape(DisplayName, _headerPaint); - c.DrawShapedText(shaper, DisplayName, (Width - shapedText.Points[^1].X) / 2, _headerHeight / 2 + _headerPaint.TextSize / 2 - 10, _headerPaint); + c.DrawShapedText(shaper, DisplayName, Width / 2f, _headerHeight / 2f + _headerPaint.TextSize / 2 - 10, _headerPaint); } private void DrawQuests(SKCanvas c) @@ -137,4 +136,4 @@ public class BaseBundle : UCreator y += quest.Height; } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseCommunity.cs b/FModel/Creator/Bases/FN/BaseCommunity.cs index 761725c9..4e63ac13 100644 --- a/FModel/Creator/Bases/FN/BaseCommunity.cs +++ b/FModel/Creator/Bases/FN/BaseCommunity.cs @@ -155,10 +155,9 @@ public class BaseCommunity : BaseIcon } var shaper = new CustomSKShaper(DisplayNamePaint.Typeface); - var shapedText = shaper.Shape(DisplayName, DisplayNamePaint); var x = font.Alignment switch { - SKTextAlign.Center => (Width - shapedText.Points[^1].X) / 2f, + SKTextAlign.Center => Width / 2f, _ => font.X }; @@ -192,10 +191,9 @@ public class BaseCommunity : BaseIcon } var shaper = new CustomSKShaper(DescriptionPaint.Typeface); - var shapedText = shaper.Shape(Description, DescriptionPaint); var x = font.Alignment switch { - SKTextAlign.Center => (Width - shapedText.Points[^1].X) / 2f, + SKTextAlign.Center => Width / 2f, _ => font.X }; @@ -236,11 +234,9 @@ public class BaseCommunity : BaseIcon DisplayNamePaint.Typeface = Utils.Typefaces.OnTheFly(path); var shaper = new CustomSKShaper(DisplayNamePaint.Typeface); - var shapedText = shaper.Shape(text, DisplayNamePaint); var x = font.Alignment switch { - SKTextAlign.Center => (Width - shapedText.Points[^1].X) / 2f, - SKTextAlign.Right => font.X - DisplayNamePaint.MeasureText(text), + SKTextAlign.Center => Width / 2f, _ => font.X }; diff --git a/FModel/Creator/Bases/FN/BaseIconStats.cs b/FModel/Creator/Bases/FN/BaseIconStats.cs index 3a25871f..4ee9a578 100644 --- a/FModel/Creator/Bases/FN/BaseIconStats.cs +++ b/FModel/Creator/Bases/FN/BaseIconStats.cs @@ -217,8 +217,7 @@ public class BaseIconStats : BaseIcon } var shaper = new CustomSKShaper(_informationPaint.Typeface); - shaper.Shape(DisplayName, _informationPaint); - c.DrawShapedText(shaper, DisplayName, _headerHeight + _headerHeight / 3 + 10, _headerHeight / 2 + _informationPaint.TextSize / 3, _informationPaint); + c.DrawShapedText(shaper, DisplayName, _headerHeight + _headerHeight / 3 + 10, _headerHeight / 2f + _informationPaint.TextSize / 3, _informationPaint); } private void DrawStatistics(SKCanvas c) @@ -270,7 +269,6 @@ public class IconStat } var shaper = new CustomSKShaper(_statPaint.Typeface); - shaper.Shape(_statName, _statPaint); c.DrawShapedText(shaper, _statName, 50, y + 10, _statPaint); _statPaint.TextAlign = SKTextAlign.Right; diff --git a/FModel/Creator/Bases/FN/BaseItemAccessToken.cs b/FModel/Creator/Bases/FN/BaseItemAccessToken.cs index fb621d6f..3df2e490 100644 --- a/FModel/Creator/Bases/FN/BaseItemAccessToken.cs +++ b/FModel/Creator/Bases/FN/BaseItemAccessToken.cs @@ -76,7 +76,7 @@ public class BaseItemAccessToken : UCreator var shaper = new CustomSKShaper(DisplayNamePaint.Typeface); var shapedText = shaper.Shape(DisplayName, DisplayNamePaint); - c.DrawShapedText(shaper, DisplayName, left - shapedText.Points[^1].X / 2, _icon.Margin * 8 + size, DisplayNamePaint); + c.DrawShapedText(shaper, DisplayName, left - shapedText.Width / 2, _icon.Margin * 8 + size, DisplayNamePaint); float topBase = _icon.Margin + size * 2; if (!string.IsNullOrEmpty(_unlockedDescription)) @@ -96,4 +96,4 @@ public class BaseItemAccessToken : UCreator var h = Width - _icon.Margin - topBase; c.DrawBitmap(_icon.Preview ?? _icon.DefaultPreview, new SKRect(left - h / 2, topBase, left + h / 2, Width - _icon.Margin), ImagePaint); } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseQuest.cs b/FModel/Creator/Bases/FN/BaseQuest.cs index 0a35dc21..4c0364b2 100644 --- a/FModel/Creator/Bases/FN/BaseQuest.cs +++ b/FModel/Creator/Bases/FN/BaseQuest.cs @@ -233,7 +233,6 @@ public class BaseQuest : BaseIcon } var shaper = new CustomSKShaper(_informationPaint.Typeface); - shaper.Shape(DisplayName, _informationPaint); c.DrawShapedText(shaper, DisplayName, Height, y + 50, _informationPaint); } @@ -263,4 +262,4 @@ public class BaseQuest : BaseIcon _reward.DrawQuest(c, new SKRect(Height, outY + 25, Width - 20, y + Height - 25)); } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseSeason.cs b/FModel/Creator/Bases/FN/BaseSeason.cs index 2d06deb3..c97163b5 100644 --- a/FModel/Creator/Bases/FN/BaseSeason.cs +++ b/FModel/Creator/Bases/FN/BaseSeason.cs @@ -136,8 +136,7 @@ public class BaseSeason : UCreator } var shaper = new CustomSKShaper(_headerPaint.Typeface); - var shapedText = shaper.Shape(DisplayName, _headerPaint); - c.DrawShapedText(shaper, DisplayName, (Width - shapedText.Points[^1].X) / 2, _headerHeight / 2 + _headerPaint.TextSize / 2 - 10, _headerPaint); + c.DrawShapedText(shaper, DisplayName, Width / 2f, _headerHeight / 2f + _headerPaint.TextSize / 2 - 10, _headerPaint); } private void DrawBookSchedule(SKCanvas c) @@ -156,4 +155,4 @@ public class BaseSeason : UCreator x = 20; } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseUserControl.cs b/FModel/Creator/Bases/FN/BaseUserControl.cs index 768ced14..a4e5bd86 100644 --- a/FModel/Creator/Bases/FN/BaseUserControl.cs +++ b/FModel/Creator/Bases/FN/BaseUserControl.cs @@ -146,7 +146,6 @@ public class BaseUserControl : UCreator } var shaper = new CustomSKShaper(_displayNamePaint.Typeface); - shaper.Shape(DisplayName, _displayNamePaint); c.DrawShapedText(shaper, DisplayName, Margin, Margin + _displayNamePaint.TextSize, _displayNamePaint); #if DEBUG c.DrawRect(new SKRect(Margin, Margin, Width - Margin, Margin + _displayNamePaint.TextSize), new SKPaint { Color = SKColors.Blue, IsStroke = true }); diff --git a/FModel/Creator/Bases/FN/Reward.cs b/FModel/Creator/Bases/FN/Reward.cs index 908dd7d6..0e5aad43 100644 --- a/FModel/Creator/Bases/FN/Reward.cs +++ b/FModel/Creator/Bases/FN/Reward.cs @@ -75,7 +75,6 @@ public class Reward } var shaper = new CustomSKShaper(_rewardPaint.Typeface); - shaper.Shape(_rewardQuantity, _rewardPaint); c.DrawShapedText(shaper, _rewardQuantity, rect.Left + rect.Height + 25, rect.MidY + 20, _rewardPaint); } else @@ -149,4 +148,4 @@ public class Reward } } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/UCreator.cs b/FModel/Creator/Bases/UCreator.cs index 7295c450..74b1e418 100644 --- a/FModel/Creator/Bases/UCreator.cs +++ b/FModel/Creator/Bases/UCreator.cs @@ -166,7 +166,7 @@ public abstract class UCreator var shaper = new CustomSKShaper(DisplayNamePaint.Typeface); var shapedText = shaper.Shape(DisplayName, DisplayNamePaint); - var x = (Width - shapedText.Points[^1].X) / 2; + var x = Width / 2f; var y = _STARTER_TEXT_POSITION + _NAME_TEXT_SIZE; switch (Style) @@ -174,14 +174,15 @@ public abstract class UCreator case EIconStyle.Flat: { DisplayNamePaint.TextAlign = SKTextAlign.Right; - x = Width - Margin * 2 - shapedText.Points[^1].X; + x = Width - Margin * 2; break; } } #if DEBUG - c.DrawLine(x, 0, x, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true }); - c.DrawLine(x + shapedText.Points[^1].X, 0, x + shapedText.Points[^1].X, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true }); + var halfWidth = shapedText.Width / 2f; + c.DrawLine(x - halfWidth, 0, x - halfWidth, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true }); + c.DrawLine(x + halfWidth, 0, x + halfWidth, Width, new SKPaint { Color = SKColors.Blue, IsStroke = true }); c.DrawRect(new SKRect(Margin, _STARTER_TEXT_POSITION, Width - Margin, y), new SKPaint { Color = SKColors.Blue, IsStroke = true }); #endif @@ -216,8 +217,6 @@ public abstract class UCreator case SKTextAlign.Left: _shortDescriptionPaint.Typeface = Utils.Typefaces.Bottom ?? Utils.Typefaces.DisplayName; var shaper = new CustomSKShaper(_shortDescriptionPaint.Typeface); - shaper.Shape(text, _shortDescriptionPaint); - c.DrawShapedText(shaper, text, Margin * 2.5f, Width - Margin * 2.5f, _shortDescriptionPaint); break; case SKTextAlign.Right: diff --git a/FModel/Creator/Utils.cs b/FModel/Creator/Utils.cs index 5e33bbfa..410b3ac9 100644 --- a/FModel/Creator/Utils.cs +++ b/FModel/Creator/Utils.cs @@ -204,9 +204,6 @@ public static class Utils return string.Empty; } - public static string FixPath(string weirdPath) => - _applicationView.CUE4Parse.Provider.FixPath(weirdPath, StringComparison.Ordinal); - public static void DrawCenteredMultilineText(SKCanvas c, string text, int maxCount, int size, int margin, SKTextAlign side, SKRect area, SKPaint paint) { var lineHeight = paint.TextSize * 1.2f; @@ -233,8 +230,8 @@ public static class Utils y += lineHeight; var x = side switch { - SKTextAlign.Center => area.MidX - shapedText.Points[^1].X / 2, - SKTextAlign.Right => size - margin - shapedText.Points[^1].X, + SKTextAlign.Center => area.MidX - shapedText.Width / 2, + SKTextAlign.Right => size - margin - shapedText.Width, SKTextAlign.Left => margin, _ => throw new NotImplementedException() }; @@ -266,8 +263,8 @@ public static class Utils var x = side switch { - SKTextAlign.Center => area.MidX - shapedText.Points[^1].X / 2, - SKTextAlign.Right => size - margin - shapedText.Points[^1].X, + SKTextAlign.Center => area.MidX - shapedText.Width / 2, + SKTextAlign.Right => size - margin - shapedText.Width, SKTextAlign.Left => area.Left, _ => throw new NotImplementedException() }; diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 76fd09f2..ded384a9 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -5,9 +5,9 @@ net6.0-windows true FModel.ico - 4.4.3.0 - 4.4.3.0 - 4.4.3.0 + 4.4.3.1 + 4.4.3.1 + 4.4.3.1 false true win-x64 @@ -135,22 +135,22 @@ - - + + - + - + - + - - + + diff --git a/FModel/Framework/CustomSKShaper.cs b/FModel/Framework/CustomSKShaper.cs index ecd8009c..c7a0756d 100644 --- a/FModel/Framework/CustomSKShaper.cs +++ b/FModel/Framework/CustomSKShaper.cs @@ -58,7 +58,7 @@ public class CustomSKShaper : SKShaper points[i] = new SKPoint(xOffset + pos[i].XOffset * textSizeX, yOffset - pos[i].YOffset * textSizeY); } - return new Result(codepoints, clusters, points); + return new Result(codepoints, clusters, points, points[^1].X); } public new Result Shape(string text, SKPaint paint) => Shape(text, 0, 0, paint); @@ -87,4 +87,4 @@ public class CustomSKShaper : SKShaper buffer.GuessSegmentProperties(); return Shape(buffer, xOffset, yOffset, paint); } -} \ No newline at end of file +} diff --git a/FModel/Framework/JsonNetSerializer.cs b/FModel/Framework/JsonNetSerializer.cs index 68daf367..c4bab9c3 100644 --- a/FModel/Framework/JsonNetSerializer.cs +++ b/FModel/Framework/JsonNetSerializer.cs @@ -22,9 +22,9 @@ public class JsonNetSerializer : IRestSerializer, ISerializer, IDeserializer public ISerializer Serializer => this; public IDeserializer Deserializer => this; - public string ContentType { get; set; } = "application/json"; - public string[] AcceptedContentTypes => RestSharp.Serializers.ContentType.JsonAccept; - public SupportsContentType SupportsContentType => contentType => contentType.EndsWith("json", StringComparison.InvariantCultureIgnoreCase); + public ContentType ContentType { get; set; } = ContentType.Json; + public string[] AcceptedContentTypes => ContentType.JsonAccept; + public SupportsContentType SupportsContentType => contentType => contentType.Value.EndsWith("json", StringComparison.InvariantCultureIgnoreCase); public DataFormat DataFormat => DataFormat.Json; } diff --git a/FModel/ViewModels/ApiEndpointViewModel.cs b/FModel/ViewModels/ApiEndpointViewModel.cs index c880b891..00927593 100644 --- a/FModel/ViewModels/ApiEndpointViewModel.cs +++ b/FModel/ViewModels/ApiEndpointViewModel.cs @@ -9,14 +9,11 @@ namespace FModel.ViewModels; public class ApiEndpointViewModel { - private readonly RestClient _client = new RestClient + private readonly RestClient _client = new (new RestClientOptions { - Options = - { - UserAgent = $"FModel/{Constants.APP_VERSION}", - MaxTimeout = 3 * 1000 - } - }.UseSerializer(); + UserAgent = $"FModel/{Constants.APP_VERSION}", + MaxTimeout = 3 * 1000 + }, configureSerialization: s => s.UseSerializer()); public FortniteApiEndpoint FortniteApi { get; } public ValorantApiEndpoint ValorantApi { get; } diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index 59dff3fb..16f2c2b8 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -32,6 +32,7 @@ using CUE4Parse.UE4.Wwise; using CUE4Parse_Conversion; using CUE4Parse_Conversion.Sounds; using CUE4Parse.FileProvider.Objects; +using CUE4Parse.UE4.Objects.Core.Serialization; using EpicManifestParser.Objects; using FModel.Creator; using FModel.Extensions; @@ -132,7 +133,7 @@ public class CUE4ParseViewModel : ViewModel Provider = new StreamedFileProvider("FortniteLive", true, new VersionContainer( UserSettings.Default.OverridedGame[Game], UserSettings.Default.OverridedPlatform, - customVersions: UserSettings.Default.OverridedCustomVersions[Game], + customVersions: new FCustomVersionContainer(UserSettings.Default.OverridedCustomVersions[Game]), optionOverrides: UserSettings.Default.OverridedOptions[Game])); break; } @@ -142,7 +143,7 @@ public class CUE4ParseViewModel : ViewModel Provider = new StreamedFileProvider("ValorantLive", true, new VersionContainer( UserSettings.Default.OverridedGame[Game], UserSettings.Default.OverridedPlatform, - customVersions: UserSettings.Default.OverridedCustomVersions[Game], + customVersions: new FCustomVersionContainer(UserSettings.Default.OverridedCustomVersions[Game]), optionOverrides: UserSettings.Default.OverridedOptions[Game])); break; } @@ -152,7 +153,7 @@ public class CUE4ParseViewModel : ViewModel if (gameDirectory.Contains("eFootball")) parent = gameDirectory.SubstringBeforeLast("\\pak").SubstringAfterLast("\\"); Game = parent.ToEnum(FGame.Unknown); var versions = new VersionContainer(UserSettings.Default.OverridedGame[Game], UserSettings.Default.OverridedPlatform, - customVersions: UserSettings.Default.OverridedCustomVersions[Game], + customVersions: new FCustomVersionContainer(UserSettings.Default.OverridedCustomVersions[Game]), optionOverrides: UserSettings.Default.OverridedOptions[Game], mapStructTypesOverrides: UserSettings.Default.OverridedMapStructTypes[Game]); @@ -185,7 +186,7 @@ public class CUE4ParseViewModel : ViewModel case FGame.Unknown when UserSettings.Default.ManualGames.TryGetValue(gameDirectory, out var settings): { versions = new VersionContainer(settings.OverridedGame, UserSettings.Default.OverridedPlatform, - customVersions: settings.OverridedCustomVersions, + customVersions: new FCustomVersionContainer(settings.OverridedCustomVersions), optionOverrides: settings.OverridedOptions, mapStructTypesOverrides: settings.OverridedMapStructTypes); goto default; @@ -549,6 +550,7 @@ public class CUE4ParseViewModel : ViewModel { FLogger.Append(ELog.Information, () => FLogger.Text($"{LocalizedResourcesCount} localized resources loaded for '{UserSettings.Default.AssetLanguage.GetDescription()}'", Constants.WHITE, true)); + Utils.Typefaces = new Typefaces(this); } } private Task LoadGameLocalizedResources() @@ -607,7 +609,7 @@ public class CUE4ParseViewModel : ViewModel { foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); Extract(cancellationToken, asset.FullPath, TabControl.HasNoTabs); } @@ -617,7 +619,7 @@ public class CUE4ParseViewModel : ViewModel { foreach (var asset in folder.AssetsList.Assets) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); try { diff --git a/FModel/ViewModels/Commands/LoadCommand.cs b/FModel/ViewModels/Commands/LoadCommand.cs index fbdf0385..f11c9e4a 100644 --- a/FModel/ViewModels/Commands/LoadCommand.cs +++ b/FModel/ViewModels/Commands/LoadCommand.cs @@ -56,7 +56,6 @@ public class LoadCommand : ViewModelCommand await Task.WhenAll( _applicationView.CUE4Parse.LoadLocalizedResources(), // load locres if not already loaded, _applicationView.CUE4Parse.LoadVirtualPaths(), // load virtual paths if not already loaded - Task.Run(() => Utils.Typefaces = new Typefaces(_applicationView.CUE4Parse)), _threadWorkerView.Begin(cancellationToken => { // filter what to show diff --git a/FModel/ViewModels/Commands/MenuCommand.cs b/FModel/ViewModels/Commands/MenuCommand.cs index f61dc8df..89d870a6 100644 --- a/FModel/ViewModels/Commands/MenuCommand.cs +++ b/FModel/ViewModels/Commands/MenuCommand.cs @@ -111,7 +111,7 @@ public class MenuCommand : ViewModelCommand if (!expand && folder.IsExpanded) { folder.IsExpanded = false; - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); } @@ -129,7 +129,7 @@ public class MenuCommand : ViewModelCommand for (var node = nodes.Last; node != null; node = node.Previous) { node.Value.IsExpanded = true; - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); } } diff --git a/FModel/ViewModels/Commands/RightClickMenuCommand.cs b/FModel/ViewModels/Commands/RightClickMenuCommand.cs index ab009a4b..1da8395e 100644 --- a/FModel/ViewModels/Commands/RightClickMenuCommand.cs +++ b/FModel/ViewModels/Commands/RightClickMenuCommand.cs @@ -29,7 +29,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Extract_New_Tab": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, true); } @@ -37,7 +37,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Export_Data": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.ExportData(asset.FullPath); } @@ -45,7 +45,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Properties": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Properties); } @@ -53,7 +53,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Textures": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Textures); } @@ -61,7 +61,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Models": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Meshes | EBulkType.Auto); } @@ -69,7 +69,7 @@ public class RightClickMenuCommand : ViewModelCommand case "Assets_Save_Animations": foreach (var asset in assetItems) { - Thread.Yield(); + Thread.Sleep(10); cancellationToken.ThrowIfCancellationRequested(); contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Animations | EBulkType.Auto); } diff --git a/FModel/ViewModels/GameSelectorViewModel.cs b/FModel/ViewModels/GameSelectorViewModel.cs index 8fac24cb..1ffa43bf 100644 --- a/FModel/ViewModels/GameSelectorViewModel.cs +++ b/FModel/ViewModels/GameSelectorViewModel.cs @@ -99,20 +99,20 @@ public class GameSelectorViewModel : ViewModel private IEnumerable EnumerateDetectedGames() { - yield return GetUnrealEngineGame("Fortnite"); + yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks"); yield return new DetectedGame { GameName = "Fortnite [LIVE]", GameDirectory = Constants._FN_LIVE_TRIGGER }; - yield return GetUnrealEngineGame("Pewee"); - yield return GetUnrealEngineGame("Rosemallow"); - yield return GetUnrealEngineGame("Catnip"); - yield return GetUnrealEngineGame("AzaleaAlpha"); - yield return GetUnrealEngineGame("WorldExplorersLive"); - yield return GetUnrealEngineGame("Newt"); - yield return GetUnrealEngineGame("shoebill"); - yield return GetUnrealEngineGame("Snoek"); - yield return GetUnrealEngineGame("a99769d95d8f400baad1f67ab5dfe508"); - yield return GetUnrealEngineGame("Nebula"); - yield return GetUnrealEngineGame("711c5e95dc094ca58e5f16bd48e751d6"); - yield return GetUnrealEngineGame("9361c8c6d2f34b42b5f2f61093eedf48"); + yield return GetUnrealEngineGame("Pewee", "\\RogueCompany\\Content\\Paks"); + yield return GetUnrealEngineGame("Rosemallow", "\\Indiana\\Content\\Paks"); + yield return GetUnrealEngineGame("Catnip", "\\OakGame\\Content\\Paks"); + yield return GetUnrealEngineGame("AzaleaAlpha", "\\Prospect\\Content\\Paks"); + yield return GetUnrealEngineGame("WorldExplorersLive", "\\WorldExplorers\\Content\\Paks"); + yield return GetUnrealEngineGame("Newt", "\\g3\\Content\\Paks"); + yield return GetUnrealEngineGame("shoebill", "\\SwGame\\Content\\Paks"); + yield return GetUnrealEngineGame("Snoek", "\\StateOfDecay2\\Content\\Paks"); + yield return GetUnrealEngineGame("a99769d95d8f400baad1f67ab5dfe508", "\\Core\\Platform\\Content\\Paks"); + yield return GetUnrealEngineGame("Nebula", "\\BendGame\\Content"); + yield return GetUnrealEngineGame("711c5e95dc094ca58e5f16bd48e751d6", "\\MultiVersus\\Content\\Paks"); + yield return GetUnrealEngineGame("9361c8c6d2f34b42b5f2f61093eedf48", "\\TslGame\\Content\\Paks"); yield return GetRiotGame("VALORANT", "ShooterGame\\Content\\Paks"); yield return new DetectedGame { GameName = "Valorant [LIVE]", GameDirectory = Constants._VAL_LIVE_TRIGGER }; yield return GetMojangGame("MinecraftDungeons", "\\dungeons\\dungeons\\Dungeons\\Content\\Paks"); @@ -129,22 +129,22 @@ public class GameSelectorViewModel : ViewModel } private LauncherInstalled _launcherInstalled; - private DetectedGame GetUnrealEngineGame(string gameName) + private DetectedGame GetUnrealEngineGame(string gameName, string pakDirectory) { _launcherInstalled ??= GetDriveLauncherInstalls("ProgramData\\Epic\\UnrealEngineLauncher\\LauncherInstalled.dat"); if (_launcherInstalled?.InstallationList != null) { foreach (var installationList in _launcherInstalled.InstallationList) { - if (installationList.AppName.Equals(gameName, StringComparison.OrdinalIgnoreCase)) + var gameDir = $"{installationList.InstallLocation}{pakDirectory}"; + if (installationList.AppName.Equals(gameName, StringComparison.OrdinalIgnoreCase) && Directory.Exists(gameDir)) { - var pak = Directory.GetDirectories(installationList.InstallLocation, "Paks*", SearchOption.AllDirectories); - if (pak.Length > 0) return new DetectedGame { GameName = installationList.AppName, GameDirectory = pak[0] }; + Log.Debug("Found {GameName} in LauncherInstalled.dat", gameName); + return new DetectedGame { GameName = installationList.AppName, GameDirectory = gameDir }; } } } - Log.Warning("Could not find {GameName} in LauncherInstalled.dat", gameName); return null; } @@ -156,12 +156,15 @@ public class GameSelectorViewModel : ViewModel { foreach (var (key, _) in _riotClientInstalls.AssociatedClient) { - if (key.Contains(gameName, StringComparison.OrdinalIgnoreCase)) - return new DetectedGame { GameName = gameName, GameDirectory = $"{key.Replace('/', '\\')}{pakDirectory}" }; + var gameDir = $"{key.Replace('/', '\\')}{pakDirectory}"; + if (key.Contains(gameName, StringComparison.OrdinalIgnoreCase) && Directory.Exists(gameDir)) + { + Log.Debug("Found {GameName} in RiotClientInstalls.json", gameName); + return new DetectedGame { GameName = gameName, GameDirectory = gameDir }; + } } } - Log.Warning("Could not find {GameName} in RiotClientInstalls.json", gameName); return null; } @@ -170,9 +173,15 @@ public class GameSelectorViewModel : ViewModel { _launcherSettings ??= GetDataLauncherInstalls("\\.minecraft\\launcher_settings.json"); if (_launcherSettings is { ProductLibraryDir: { } }) - return new DetectedGame { GameName = gameName, GameDirectory = $"{_launcherSettings.ProductLibraryDir}{pakDirectory}" }; + { + var gameDir = $"{_launcherSettings.ProductLibraryDir}{pakDirectory}"; + if (Directory.Exists(gameDir)) + { + Log.Debug("Found {GameName} in launcher_settings.json", gameName); + return new DetectedGame { GameName = gameName, GameDirectory = gameDir }; + } + } - Log.Warning("Could not find {GameName} in launcher_settings.json", gameName); return null; } @@ -180,9 +189,11 @@ public class GameSelectorViewModel : ViewModel { var steamInfo = SteamDetection.GetSteamGameById(id); if (steamInfo is not null) + { + Log.Debug("Found {GameName} in steam manifests", steamInfo.Name); return new DetectedGame { GameName = steamInfo.Name, GameDirectory = $"{steamInfo.GameRoot}{pakDirectory}" }; + } - Log.Warning("Could not find {GameId} in steam manifests", id); return null; } @@ -198,10 +209,13 @@ public class GameSelectorViewModel : ViewModel // ignored } - if (!string.IsNullOrEmpty(installLocation)) - return new DetectedGame { GameName = key, GameDirectory = $"{installLocation}{pakDirectory}" }; + var gameDir = $"{installLocation}{pakDirectory}"; + if (Directory.Exists(gameDir)) + { + Log.Debug("Found {GameName} in the registry", key); + return new DetectedGame { GameName = key, GameDirectory = gameDir }; + } - Log.Warning("Could not find {GameName} in the registry", key); return null; } @@ -220,10 +234,13 @@ public class GameSelectorViewModel : ViewModel // ignored } - if (!string.IsNullOrEmpty(installLocation)) - return new DetectedGame { GameName = displayName, GameDirectory = $"{installLocation}{pakDirectory}" }; + var gameDir = $"{installLocation}{pakDirectory}"; + if (Directory.Exists(gameDir)) + { + Log.Debug("Found {GameName} in the registry", key); + return new DetectedGame { GameName = displayName, GameDirectory = gameDir }; + } - Log.Warning("Could not find {GameName} in the registry", key); return null; } @@ -234,11 +251,10 @@ public class GameSelectorViewModel : ViewModel var launcher = $"{drive.Name}{jsonFile}"; if (!File.Exists(launcher)) continue; - Log.Information("\"{Launcher}\" found in drive \"{DriveName}\"", launcher, drive.Name); + Log.Debug("\"{Launcher}\" found in drive \"{DriveName}\"", launcher, drive.Name); return JsonConvert.DeserializeObject(File.ReadAllText(launcher)); } - Log.Warning("\"{JsonFile}\" not found in any drives", jsonFile); return default; } @@ -248,11 +264,10 @@ public class GameSelectorViewModel : ViewModel var launcher = $"{appData}{jsonFile}"; if (File.Exists(launcher)) { - Log.Information("\"{Launcher}\" found in \"{AppData}\"", launcher, appData); + Log.Debug("\"{Launcher}\" found in \"{AppData}\"", launcher, appData); return JsonConvert.DeserializeObject(File.ReadAllText(launcher)); } - Log.Warning("\"{Json}\" not found anywhere", jsonFile); return default; } @@ -321,7 +336,10 @@ public class GameSelectorViewModel : ViewModel private static List GetSteamApps(IEnumerable steamLibs) { var apps = new List(); - foreach (var files in steamLibs.Select(lib => Path.Combine(lib, "SteamApps")).Select(appMetaDataPath => Directory.GetFiles(appMetaDataPath, "*.acf"))) + foreach (var files in steamLibs + .Select(lib => Path.Combine(lib, "SteamApps")) + .Select(appMetaDataPath => Directory.Exists(appMetaDataPath) ? Directory.GetFiles(appMetaDataPath, "*.acf") : null) + .Where(files => files != null)) { apps.AddRange(files.Select(GetAppInfo).Where(appInfo => appInfo != null)); } @@ -346,16 +364,16 @@ public class GameSelectorViewModel : ViewModel !dic.TryGetValue("name", out var name) || !dic.TryGetValue("installDir", out var installDir)) return null; - var path = Path.GetDirectoryName(appMetaFile); + var path = Path.GetDirectoryName(appMetaFile) ?? ""; var libGameRoot = Path.Combine(path, "common", installDir); - return !Directory.Exists(libGameRoot) ? null : new AppInfo { Id = appId, Name = name, GameRoot = libGameRoot }; + return Directory.Exists(libGameRoot) ? new AppInfo { Id = appId, Name = name, GameRoot = libGameRoot } : null; } private static List GetSteamLibs() { var steamPath = GetSteamPath(); - if (steamPath == null) return new List(); + if (steamPath == null || !Directory.Exists(steamPath)) return new List(); var libraries = new List { steamPath }; var listFile = Path.Combine(steamPath, @"steamapps\libraryfolders.vdf"); @@ -366,7 +384,7 @@ public class GameSelectorViewModel : ViewModel var match = Regex.Match(line, @"""(?\w:\\\\.*)"""); if (!match.Success) continue; var path = match.Groups["path"].Value.Replace(@"\\", @"\"); - if (Directory.Exists(path)) + if (Directory.Exists(path) && !libraries.Contains(path)) { libraries.Add(path); } diff --git a/FModel/ViewModels/MapViewerViewModel.cs b/FModel/ViewModels/MapViewerViewModel.cs index f5bf9c5c..b9a36dcf 100644 --- a/FModel/ViewModels/MapViewerViewModel.cs +++ b/FModel/ViewModels/MapViewerViewModel.cs @@ -430,30 +430,28 @@ public class MapViewerViewModel : ViewModel !poiData.TryGetValue(out FName discoverBackend, "DiscoverObjectiveBackendName")) continue; var shaper = new CustomSKShaper(_textPaint.Typeface); - var shapedText = shaper.Shape(text.Text, _textPaint); - if (discoverBackend.Text.Contains("papaya", StringComparison.OrdinalIgnoreCase)) { _fillPaint.StrokeWidth = 5; var vector = GetMapPosition(worldLocation, _prRadius); prLandmarks.DrawPoint(vector.X, vector.Y, _pathPaint); - prLandmarks.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _fillPaint); - prLandmarks.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _textPaint); + prLandmarks.DrawShapedText(shaper, text.Text, vector.X, vector.Y - 12.5F, _fillPaint); + prLandmarks.DrawShapedText(shaper, text.Text, vector.X, vector.Y - 12.5F, _textPaint); } else if (discoveryQuest.AssetPathName.Text.Contains("landmarks", StringComparison.OrdinalIgnoreCase)) { _fillPaint.StrokeWidth = 5; var vector = GetMapPosition(worldLocation, _brRadius); brLandmarks.DrawPoint(vector.X, vector.Y, _pathPaint); - brLandmarks.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _fillPaint); - brLandmarks.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _textPaint); + brLandmarks.DrawShapedText(shaper, text.Text, vector.X, vector.Y - 12.5F, _fillPaint); + brLandmarks.DrawShapedText(shaper, text.Text, vector.X, vector.Y - 12.5F, _textPaint); } else { _fillPaint.StrokeWidth = 10; var vector = GetMapPosition(worldLocation, _brRadius); - pois.DrawShapedText(shaper, text.Text.ToUpperInvariant(), vector.X - shapedText.Points[^1].X / 2, vector.Y, _fillPaint); - pois.DrawShapedText(shaper, text.Text.ToUpperInvariant(), vector.X - shapedText.Points[^1].X / 2, vector.Y, _textPaint); + pois.DrawShapedText(shaper, text.Text.ToUpperInvariant(), vector.X, vector.Y, _fillPaint); + pois.DrawShapedText(shaper, text.Text.ToUpperInvariant(), vector.X, vector.Y, _textPaint); } } } diff --git a/FModel/Views/Snooper/Shading/TextureHelper.cs b/FModel/Views/Snooper/Shading/TextureHelper.cs index b721414c..60922845 100644 --- a/FModel/Views/Snooper/Shading/TextureHelper.cs +++ b/FModel/Views/Snooper/Shading/TextureHelper.cs @@ -50,6 +50,7 @@ public static class TextureHelper // G: Metallic // B: Whatever (AO / S / E / ...) case "CCFF7R": + case "PJ033": { texture.SwizzleMask = new [] {