added "deleted cosmetics" support for valorant + fixed egl2

This commit is contained in:
iAmAsval 2020-06-09 11:47:31 +02:00
parent 088d558aad
commit 9e60c55337
13 changed files with 173 additions and 58 deletions

View File

@ -0,0 +1,30 @@
using PakReader.Parsers.Class;
using PakReader.Parsers.PropertyTagData;
using SkiaSharp;
using System;
using System.Windows;
namespace FModel.Creator
{
public class BaseValorant
{
public SKBitmap FallbackImage;
public SKBitmap IconImage;
public string DisplayName;
public string Description;
public int Size = 512; // keep it 512 (or a multiple of 512) if you don't want blurry icons
public BaseValorant()
{
FallbackImage = SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/T_Placeholder_Item_Image.png")).Stream);
IconImage = FallbackImage;
DisplayName = "";
Description = "";
}
public BaseValorant(IUExport export, string assetFolder, ref string assetName) : this()
{
//if (export.GetExport<ArrayProperty>("ExplicitAssets") is ArrayProperty explicitAssets)
}
}
}

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace FModel.Creator.Characters
{
class PrimaryAsset
{
}
}

View File

@ -7,6 +7,7 @@ using FModel.ViewModels.ImageBox;
using PakReader.Parsers.Class;
using SkiaSharp;
using System.IO;
using System.Text.RegularExpressions;
namespace FModel.Creator
{
@ -201,5 +202,27 @@ namespace FModel.Creator
}
return false;
}
public static bool TryDrawValorantIcon(string assetPath, string exportType, IUExport export)
{
var d = new DirectoryInfo(assetPath);
string assetName = d.Name;
string assetFolder = d.Parent.Name;
//if (Regex.Match(exportType, $"{assetName.Substring(0, assetName.LastIndexOf("."))}_C", RegexOptions.IgnoreCase).Success)
//{
// BaseValorant icon = new BaseValorant(export, assetFolder, ref assetName);
// using (var ret = new SKBitmap(icon.Size, icon.Size, SKColorType.Rgba8888, SKAlphaType.Premul))
// using (var c = new SKCanvas(ret))
// {
// Watermark.DrawWatermark(c); // watermark should only be applied on icons with width = 512
// ImageBoxVm.imageBoxViewModel.Set(ret, assetName);
// }
// return true;
//}
return false;
}
}
}

View File

@ -46,56 +46,59 @@ namespace FModel.Creator.Texts
public Typefaces()
{
DefaultTypeface = SKTypeface.FromStream(Application.GetResourceStream(_BURBANK_BIG_CONDENSED_BOLD).Stream);
ArraySegment<byte>[] t = Utils.GetPropertyArraySegmentByte(_BASE_PATH + _BURBANK_BIG_CONDENSED_BLACK);
if (t != null && t.Length == 3)
BundleDefaultTypeface = SKTypeface.FromStream(t[2].AsStream());
else BundleDefaultTypeface = DefaultTypeface;
string namePath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _ASIA_ERINM :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Russian ? _BURBANK_BIG_CONDENSED_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NIS_JYAU :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_BLACK :
string.Empty);
if (!namePath.Equals(_BASE_PATH))
if (Globals.Game.ActualGame == EGame.Fortnite)
{
t = Utils.GetPropertyArraySegmentByte(namePath);
if (t != null && t.Length == 3)
DisplayNameTypeface = SKTypeface.FromStream(t[2].AsStream());
}
else DisplayNameTypeface = DefaultTypeface;
DefaultTypeface = SKTypeface.FromStream(Application.GetResourceStream(_BURBANK_BIG_CONDENSED_BOLD).Stream);
string descriptionPath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _NOTO_SANS_KR_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NOTO_SANS_JP_BOLD :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_REGULAR :
_NOTO_SANS_REGULAR);
t = Utils.GetPropertyArraySegmentByte(descriptionPath);
if (t != null && t.Length == 3)
DescriptionTypeface = SKTypeface.FromStream(t[2].AsStream());
else DescriptionTypeface = DefaultTypeface;
string bundleNamePath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _ASIA_ERINM :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Russian ? _BURBANK_BIG_CONDENSED_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NIS_JYAU :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_BLACK :
string.Empty);
if (!bundleNamePath.Equals(_BASE_PATH))
{
t = Utils.GetPropertyArraySegmentByte(bundleNamePath);
ArraySegment<byte>[] t = Utils.GetPropertyArraySegmentByte(_BASE_PATH + _BURBANK_BIG_CONDENSED_BLACK);
if (t != null && t.Length == 3)
BundleDisplayNameTypeface = SKTypeface.FromStream(t[2].AsStream());
BundleDefaultTypeface = SKTypeface.FromStream(t[2].AsStream());
else BundleDefaultTypeface = DefaultTypeface;
string namePath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _ASIA_ERINM :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Russian ? _BURBANK_BIG_CONDENSED_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NIS_JYAU :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_BLACK :
string.Empty);
if (!namePath.Equals(_BASE_PATH))
{
t = Utils.GetPropertyArraySegmentByte(namePath);
if (t != null && t.Length == 3)
DisplayNameTypeface = SKTypeface.FromStream(t[2].AsStream());
}
else DisplayNameTypeface = DefaultTypeface;
string descriptionPath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _NOTO_SANS_KR_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NOTO_SANS_JP_BOLD :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_REGULAR :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_REGULAR :
_NOTO_SANS_REGULAR);
t = Utils.GetPropertyArraySegmentByte(descriptionPath);
if (t != null && t.Length == 3)
DescriptionTypeface = SKTypeface.FromStream(t[2].AsStream());
else DescriptionTypeface = DefaultTypeface;
string bundleNamePath = _BASE_PATH + (
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Korean ? _ASIA_ERINM :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Russian ? _BURBANK_BIG_CONDENSED_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Japanese ? _NIS_JYAU :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Arabic ? _NOTO_SANS_ARABIC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.TraditionalChinese ? _NOTO_SANS_TC_BLACK :
Properties.Settings.Default.AssetsLanguage == (long)ELanguage.Chinese ? _NOTO_SANS_SC_BLACK :
string.Empty);
if (!bundleNamePath.Equals(_BASE_PATH))
{
t = Utils.GetPropertyArraySegmentByte(bundleNamePath);
if (t != null && t.Length == 3)
BundleDisplayNameTypeface = SKTypeface.FromStream(t[2].AsStream());
}
else BundleDisplayNameTypeface = BundleDefaultTypeface;
}
else BundleDisplayNameTypeface = BundleDefaultTypeface;
}
public bool NeedReload(bool forceReload) => forceReload ?

View File

@ -23,12 +23,15 @@ namespace FModel.Grabber.Paks
{
if (string.IsNullOrEmpty(Properties.Settings.Default.PakPath))
{
var launcher = new FLauncher();
if ((bool)launcher.ShowDialog())
Application.Current.Dispatcher.Invoke(delegate
{
Properties.Settings.Default.PakPath = launcher.Path;
Properties.Settings.Default.Save();
}
var launcher = new FLauncher();
if ((bool)launcher.ShowDialog())
{
Properties.Settings.Default.PakPath = launcher.Path;
Properties.Settings.Default.Save();
}
});
}
// define the current game thank to the pak path

View File

@ -64,8 +64,12 @@ namespace PakReader.Pak
}
public string GetFirstExportType() => ExportTypes[0];
public string GetSecondExportType() => ExportTypes.Length > 1 ? ExportTypes[1] : GetFirstExportType();
public IUExport[] GetAllExports() => Exports;
public IUExport GetFirstExport() => Exports[0];
public IUExport GetSecondExport() => Exports.Length > 1 ? Exports[1] : GetFirstExport();
public T GetExport<T>() where T : IUExport
{
var exports = Exports;

View File

@ -11,6 +11,7 @@ namespace PakReader.Parsers.Objects
internal UScriptStruct(PackageReader reader, FName structName) : this(reader, structName.String) { }
internal UScriptStruct(PackageReader reader, string structName)
{
//System.Diagnostics.Debug.WriteLine(structName);
Struct = structName switch
{
"LevelSequenceObjectReferenceMap" => new FLevelSequenceObjectReferenceMap(reader),

View File

@ -49,6 +49,7 @@ namespace PakReader.Parsers
ObjectClassName = ImportMap[Export.ClassIndex.AsImport].ObjectName;
else
throw new FileLoadException("Can't get class name"); // Shouldn't reach this unless the laws of math have bent to MagmaReef's will
if (ObjectClassName.String.Equals("BlueprintGeneratedClass")) continue;
var pos = Position = Export.SerialOffset - PackageFileSummary.TotalHeaderSize;
ExportTypes[i] = ObjectClassName.String;
@ -65,7 +66,7 @@ namespace PakReader.Parsers
if (pos + Export.SerialSize != Position)
{
System.Diagnostics.Debug.WriteLine($"[ExportType=${ObjectClassName.String}] Didn't read {Export.ObjectName} correctly (at {Position}, should be {pos + Export.SerialSize}, {pos + Export.SerialSize - Position} behind)");
System.Diagnostics.Debug.WriteLine($"[ExportType={ObjectClassName.String}] Didn't read {Export.ObjectName} correctly (at {Position}, should be {pos + Export.SerialSize}, {pos + Export.SerialSize - Position} behind)");
}
}
}

View File

@ -239,7 +239,9 @@ namespace FModel.Utils
}
// Creator Image
if (TryDrawIcon(entry.Name, p.GetFirstExportType(), p.GetFirstExport()))
if (Globals.Game.ActualGame == EGame.Valorant && TryDrawValorantIcon(entry.Name, p.GetSecondExportType(), p.GetSecondExport()))
return p;
else if (TryDrawIcon(entry.Name, p.GetFirstExportType(), p.GetFirstExport()))
return p;
}

View File

@ -25,9 +25,9 @@ namespace FModel.Utils
int stringLength = reader.ReadUInt16BE();
string cacheDirectory = Encoding.UTF8.GetString(reader.ReadBytes(stringLength));
if (Directory.Exists(cacheDirectory + "\\game\\FortniteGame\\Content\\Paks"))
if (Directory.Exists(cacheDirectory + "\\fn\\FortniteGame\\Content\\Paks"))
{
return cacheDirectory + "\\game\\FortniteGame\\Content\\Paks";
return cacheDirectory + "\\fn\\FortniteGame\\Content\\Paks";
}
}

View File

@ -3,6 +3,7 @@ using FModel.Windows.CustomNotifier;
using System;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
namespace FModel.Utils
{
@ -105,5 +106,34 @@ namespace FModel.Utils
if (bSave)
Properties.Settings.Default.Save();
}
public static string GetUniqueFilePath(string filePath)
{
if (File.Exists(filePath))
{
string folderPath = Path.GetDirectoryName(filePath);
string fileName = Path.GetFileNameWithoutExtension(filePath);
string fileExtension = Path.GetExtension(filePath);
int number = 1;
Match regex = Regex.Match(fileName, @"^(.+) \((\d+)\)$");
if (regex.Success)
{
fileName = regex.Groups[1].Value;
number = int.Parse(regex.Groups[2].Value);
}
do
{
number++;
string newFileName = $"{fileName} ({number}){fileExtension}";
filePath = Path.Combine(folderPath, newFileName);
}
while (File.Exists(filePath));
}
return filePath;
}
}
}

View File

@ -48,12 +48,12 @@ namespace FModel.ViewModels.AvalonEdit
{
if (autoSave)
{
string path = Properties.Settings.Default.OutputPath + "\\JSONs\\" + Path.ChangeExtension(vm.OwerName, ".json");
string path = Folders.GetUniqueFilePath(Properties.Settings.Default.OutputPath + "\\JSONs\\" + Path.ChangeExtension(vm.OwerName, ".json"));
File.WriteAllText(path, vm.Document.Text);
if (File.Exists(path))
{
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[AvalonEditViewModel]", $"{vm.OwerName} successfully saved");
FConsole.AppendText(string.Format(Properties.Resources.SaveSuccess, Path.ChangeExtension(vm.OwerName, ".json")), FColors.Green, true);
FConsole.AppendText(string.Format(Properties.Resources.SaveSuccess, Path.GetFileName(path)), FColors.Green, true);
}
}
else

View File

@ -322,7 +322,15 @@ namespace FModel.ViewModels.MenuItem
break;
}
var deleted = oldFiles.Where(kvp => !newFiles.TryGetValue(kvp.Key, out var _) && kvp.Key.StartsWith("/FortniteGame/Content/Athena/Items/Cosmetics/")).ToDictionary(x => x.Key, x => x.Value);
string cosmeticsPath;
if (Globals.Game.ActualGame == EGame.Fortnite)
cosmeticsPath = $"/{Folders.GetGameName()}/Content/Athena/Items/Cosmetics/";
else if (Globals.Game.ActualGame == EGame.Valorant)
cosmeticsPath = $"/{Folders.GetGameName()}/Content/Labels/";
else
cosmeticsPath = "/gqdozqhndpioqgnq/"; // just corrupting it so it doesn't trigger all assets
var deleted = oldFiles.Where(kvp => !newFiles.TryGetValue(kvp.Key, out var _) && kvp.Key.StartsWith(cosmeticsPath)).ToDictionary(x => x.Key, x => x.Value);
if (deleted.Count > 0)
{
FConsole.AppendText(Properties.Resources.RemovedRenamedCosmetics, FColors.Red, true);