implemented usmap

This commit is contained in:
iAmAsval 2021-01-04 14:12:08 +01:00
parent d05bed14a4
commit 841e76d2d7
23 changed files with 298 additions and 229 deletions

View File

@ -1,18 +1,22 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.29806.167 VisualStudioVersion = 16.0.30804.86
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel\FModel.csproj", "{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel\FModel.csproj", "{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Debug|Any CPU.ActiveCfg = Debug|x64
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Debug|x64.ActiveCfg = Debug|x64 {A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Debug|x64.ActiveCfg = Debug|x64
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Debug|x64.Build.0 = Debug|x64 {A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Debug|x64.Build.0 = Debug|x64
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Release|Any CPU.ActiveCfg = Release|x64
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Release|x64.ActiveCfg = Release|x64 {A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Release|x64.ActiveCfg = Release|x64
{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Release|x64.Build.0 = Release|x64 {A42F8737-D056-4FA5-BEB5-AA96E1639F8A}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
@ -20,6 +24,6 @@ Global
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FE6EA91D-BBB8-4FBC-875C-25AD92EDB519} SolutionGuid = {688BAB53-42F7-45F2-AFDF-79A07771213F}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -131,6 +131,7 @@
<PackageReference Include="System.Data.HashFunction.CityHash" Version="2.0.0" /> <PackageReference Include="System.Data.HashFunction.CityHash" Version="2.0.0" />
<PackageReference Include="ToastNotifications" Version="2.5.1" /> <PackageReference Include="ToastNotifications" Version="2.5.1" />
<PackageReference Include="ToastNotifications.Messages" Version="2.5.1" /> <PackageReference Include="ToastNotifications.Messages" Version="2.5.1" />
<PackageReference Include="Usmap.NET" Version="1.0.0" />
<PackageReference Include="WriteableBitmapEx" Version="1.6.7" /> <PackageReference Include="WriteableBitmapEx" Version="1.6.7" />
</ItemGroup> </ItemGroup>

View File

@ -8,6 +8,7 @@ using FModel.Properties;
using ToastNotifications; using ToastNotifications;
using ToastNotifications.Lifetime; using ToastNotifications.Lifetime;
using ToastNotifications.Position; using ToastNotifications.Position;
using UsmapNET.Classes;
namespace FModel namespace FModel
{ {
@ -19,9 +20,9 @@ namespace FModel
/// </summary> /// </summary>
public static readonly Dictionary<string, PakFileReader> CachedPakFiles = new Dictionary<string, PakFileReader>(); public static readonly Dictionary<string, PakFileReader> CachedPakFiles = new Dictionary<string, PakFileReader>();
public static readonly Dictionary<string, FFileIoStoreReader> CachedIoStores = new Dictionary<string, FFileIoStoreReader>(); public static readonly Dictionary<string, FFileIoStoreReader> CachedIoStores = new Dictionary<string, FFileIoStoreReader>();
public static readonly Dictionary<string, FUnversionedType> CachedSchemas = new Dictionary<string, FUnversionedType>();
public static Usmap Usmap = null;
public static FIoGlobalData GlobalData = null; public static FIoGlobalData GlobalData = null;
public static Dictionary<string, Dictionary<int, PropertyInfo>> TypeMappings;
public static Dictionary<string, Dictionary<int, string>> EnumMappings;
public static readonly Notifier gNotifier = new Notifier(cfg => public static readonly Notifier gNotifier = new Notifier(cfg =>
{ {
cfg.LifetimeSupervisor = new TimeAndCountBasedLifetimeSupervisor(TimeSpan.FromSeconds(7), MaximumNotificationCount.FromCount(15)); cfg.LifetimeSupervisor = new TimeAndCountBasedLifetimeSupervisor(TimeSpan.FromSeconds(7), MaximumNotificationCount.FromCount(15));

View File

@ -0,0 +1,50 @@
using FModel.Logger;
using FModel.Utils;
using FModel.Windows.CustomNotifier;
using Newtonsoft.Json;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
namespace FModel.Grabber.Mappings
{
static class MappingsData
{
public static async Task<Mapping[]> GetData()
{
if (NetworkInterface.GetIsNetworkAvailable())
{
Mapping[] data = await Endpoints.GetJsonEndpoint<Mapping[]>(Endpoints.BENBOT_MAPPINGS, string.Empty).ConfigureAwait(false);
return data;
}
else
{
Globals.gNotifier.ShowCustomMessage("Mappings", Properties.Resources.NoInternet, "/FModel;component/Resources/wifi-strength-off.ico");
DebugHelper.WriteLine("{0} {1} {2}", "[FModel]", "[Mappings]", "No internet");
return null;
}
}
}
public class Mapping
{
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("fileName")]
public string FileName { get; set; }
[JsonProperty("hash")]
public string Hash { get; set; }
[JsonProperty("length")]
public string Length { get; set; }
[JsonProperty("uploaded")]
public string Uploaded { get; set; }
[JsonProperty("meta")]
public Metadata Meta { get; set; }
}
public class Metadata
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("compressionMethod")]
public string CompressionMethod { get; set; }
}
}

View File

@ -0,0 +1,45 @@
using FModel.Utils;
using System;
using System.IO;
using System.Threading.Tasks;
using UsmapNET.Classes;
namespace FModel.Grabber.Mappings
{
static class MappingsGrabber
{
public static async Task<bool> Load(bool forceReload = false)
{
if (Globals.Game.ActualGame == EGame.Fortnite)
{
Mapping[] benMappings = await MappingsData.GetData().ConfigureAwait(false);
if (benMappings != null)
{
foreach (Mapping mapping in benMappings)
{
if (mapping.Meta.CompressionMethod == "Brotli")
{
DirectoryInfo chunksDir = Directory.CreateDirectory(Path.Combine(Properties.Settings.Default.OutputPath, "PakChunks"));
string mappingPath = Path.Combine(chunksDir.FullName, mapping.FileName);
byte[] mappingsData;
if (!forceReload && File.Exists(mappingPath))
{
mappingsData = await File.ReadAllBytesAsync(mappingPath);
}
else
{
mappingsData = await Endpoints.GetRawDataAsync(new Uri(mapping.Url)).ConfigureAwait(false);
await File.WriteAllBytesAsync(mappingPath, mappingsData).ConfigureAwait(false);
}
Globals.Usmap = new Usmap(mappingsData);
return true;
}
}
}
}
return false;
}
}
}

View File

@ -23,19 +23,15 @@ using FModel.Windows.Search;
using FModel.Windows.Settings; using FModel.Windows.Settings;
using FModel.Windows.SoundPlayer; using FModel.Windows.SoundPlayer;
using System; using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using Newtonsoft.Json; using FModel.Grabber.Mappings;
using Newtonsoft.Json.Serialization;
using System.Net.NetworkInformation;
namespace FModel namespace FModel
{ {
@ -83,7 +79,6 @@ namespace FModel
Keys.NoKeyGoodBye(); Keys.NoKeyGoodBye();
MenuItems.FeedCustomGoTos(); MenuItems.FeedCustomGoTos();
AeConfiguration(); AeConfiguration();
LoadMappings();
if (t.Exception != null) Tasks.TaskCompleted(t.Exception); if (t.Exception != null) Tasks.TaskCompleted(t.Exception);
else StatusBarVm.statusBarViewModel.Set($"{Properties.Resources.Hello} {Environment.UserName}!", Properties.Resources.State); else StatusBarVm.statusBarViewModel.Set($"{Properties.Resources.Hello} {Environment.UserName}!", Properties.Resources.State);
@ -98,54 +93,22 @@ namespace FModel
{ {
await PaksGrabber.PopulateMenu().ConfigureAwait(false); await PaksGrabber.PopulateMenu().ConfigureAwait(false);
await AesGrabber.Load(Properties.Settings.Default.ReloadAesKeys).ConfigureAwait(false); await AesGrabber.Load(Properties.Settings.Default.ReloadAesKeys).ConfigureAwait(false);
await MappingsGrabber.Load().ConfigureAwait(false);
await CdnDataGrabber.DoCDNStuff().ConfigureAwait(false); await CdnDataGrabber.DoCDNStuff().ConfigureAwait(false);
await Folders.DownloadAndExtractVgm().ConfigureAwait(false); await Folders.DownloadAndExtractVgm().ConfigureAwait(false);
if (Properties.Settings.Default.UseDiscordRpc) DiscordIntegration.StartClient(); if (Properties.Settings.Default.UseDiscordRpc) DiscordIntegration.StartClient();
} }
private async void LoadMappings() public async void ReloadMappings(object sender, RoutedEventArgs e)
{ {
string rawMappings = "{}"; if (await MappingsGrabber.Load(true).ConfigureAwait(false))
string rawEnumMappings = "{}";
#if DEBUG
if (File.Exists("TypeMappings.json"))
{ {
rawMappings = await File.ReadAllTextAsync("TypeMappings.json"); Globals.gNotifier.ShowCustomMessage("Mappings", "Reloaded successfully");
} }
else if (NetworkInterface.GetIsNetworkAvailable()) else
{ {
rawMappings = await Endpoints.GetStringEndpoint(Endpoints.FORTNITE_TYPE_MAPPINGS); Globals.gNotifier.ShowCustomMessage("Mappings", "Fail to reload");
} }
if (File.Exists("EnumMappings.json"))
{
rawEnumMappings = await File.ReadAllTextAsync("EnumMappings.json");
}
else if (NetworkInterface.GetIsNetworkAvailable())
{
rawEnumMappings = await Endpoints.GetStringEndpoint(Endpoints.FORTNITE_ENUM_MAPPINGS);
}
#else
rawMappings = await Endpoints.GetStringEndpoint(Endpoints.FORTNITE_TYPE_MAPPINGS);
rawEnumMappings = await Endpoints.GetStringEndpoint(Endpoints.FORTNITE_ENUM_MAPPINGS);
#endif
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new CamelCaseNamingStrategy(false, false)
}
};
Globals.TypeMappings = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<int, PakReader.IO.PropertyInfo>>>(rawMappings, serializerSettings);
Globals.EnumMappings = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<int, string>>>(rawEnumMappings, serializerSettings);
}
public void ReloadMappings(object sender, RoutedEventArgs e)
{
LoadMappings();
Globals.gNotifier.ShowCustomMessage("Mappings", "Reloaded successfully");
} }
private void AeConfiguration() private void AeConfiguration()

View File

@ -27,7 +27,11 @@ namespace FModel.PakReader.IO
public static bool operator ==(FIoDirectoryIndexHandle a, FIoDirectoryIndexHandle b) => a._handle == b._handle; public static bool operator ==(FIoDirectoryIndexHandle a, FIoDirectoryIndexHandle b) => a._handle == b._handle;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(FIoDirectoryIndexHandle a, FIoDirectoryIndexHandle b) => a._handle != b._handle; public static bool operator !=(FIoDirectoryIndexHandle a, FIoDirectoryIndexHandle b) => a._handle != b._handle;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(FIoDirectoryIndexHandle b) => _handle == b._handle;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj) => obj is FIoDirectoryIndexHandle handle && Equals(handle);
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static FIoDirectoryIndexHandle FromIndex(uint index) => new FIoDirectoryIndexHandle(index); public static FIoDirectoryIndexHandle FromIndex(uint index) => new FIoDirectoryIndexHandle(index);
} }

View File

@ -17,8 +17,7 @@ namespace FModel.PakReader.IO
{ {
_zeroMask = header.ZeroMask; _zeroMask = header.ZeroMask;
_fragmentIt = header.Fragments.GetEnumerator(); _fragmentIt = header.Fragments.GetEnumerator();
if (header.HasValues) Skip();
Skip();
} }
public bool MoveNext() public bool MoveNext()

View File

@ -0,0 +1,29 @@
using System.Collections.Generic;
using UsmapNET.Classes;
namespace FModel.PakReader.IO
{
public class FUnversionedType
{
public string Name { get; }
public Dictionary<int, FUnversionedProperty> Properties { get; set; }
public FUnversionedType(string name)
{
Name = name;
Properties = new Dictionary<int, FUnversionedProperty>();
}
}
public class FUnversionedProperty
{
public string Name { get; set; }
public UsmapPropertyData Data { get; set; }
public FUnversionedProperty(UsmapProperty prop)
{
Name = prop.Name;
Data = prop.Data;
}
}
}

View File

@ -1,34 +0,0 @@
using Newtonsoft.Json;
namespace FModel.PakReader.IO
{
public class PropertyInfo
{
public string Name;
public string Type;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string StructType;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public bool? Bool;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string EnumName;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string EnumType;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string InnerType;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string ValueType;
public PropertyInfo(string name, string type, string structType = null, bool? b = null, string enumName = null, string enumType = null, string innerType = null, string valueType = null)
{
Name = name;
Type = type;
StructType = structType;
Bool = b;
EnumName = enumName;
EnumType = enumType;
InnerType = innerType;
ValueType = valueType;
}
}
}

View File

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using FModel.PakReader.IO;
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;
namespace FModel.PakReader.Parsers.Class namespace FModel.PakReader.Parsers.Class
@ -34,17 +33,18 @@ namespace FModel.PakReader.Parsers.Class
} }
} }
internal UCurveTable(IoPackageReader reader) internal UCurveTable(IoPackageReader reader, string _)
{ {
reader.ReadUInt16(); // don't ask me reader.ReadUInt16(); // don't ask me
reader.ReadUInt32(); // what this is reader.ReadUInt32(); // what this is
int NumRows = reader.ReadInt32(); int NumRows = reader.ReadInt32();
CurveTableMode = (ECurveTableMode)reader.ReadByte(); CurveTableMode = (ECurveTableMode)reader.ReadByte();
Dictionary<int, PropertyInfo> properties = CurveTableMode switch
string export = CurveTableMode switch
{ {
ECurveTableMode.RichCurves => Globals.TypeMappings["RichCurve"], ECurveTableMode.RichCurves => "RichCurve",
ECurveTableMode.SimpleCurves => Globals.TypeMappings["SimpleCurve"], ECurveTableMode.SimpleCurves => "SimpleCurve",
_ => throw new FileLoadException($"This table has an unknown mode ({CurveTableMode})") _ => throw new FileLoadException($"This table has an unknown mode ({CurveTableMode})")
}; };
@ -59,7 +59,7 @@ namespace FModel.PakReader.Parsers.Class
RowName = $"{baseName}_NK{num++:00}"; RowName = $"{baseName}_NK{num++:00}";
} }
RowMap[RowName] = new UObject(reader, properties, true); RowMap[RowName] = new UObject(reader, export, true);
} }
} }

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using FModel.PakReader.IO; using FModel.PakReader.IO;
using FModel.PakReader.Parsers.PropertyTagData; using FModel.PakReader.Parsers.PropertyTagData;
using FModel.Utils; using FModel.Utils;
@ -34,24 +34,21 @@ namespace FModel.PakReader.Parsers.Class
} }
} }
internal UDataTable(IoPackageReader reader, IReadOnlyDictionary<int, PropertyInfo> properties, string type) internal UDataTable(IoPackageReader reader, string type)
{ {
var baseObj = new UObject(reader, properties, type: type); var baseObj = new UObject(reader, type);
if (!baseObj.TryGetValue("RowStruct", out var rowStructProp) || !(rowStructProp is ObjectProperty rowStruct) || !rowStruct.Value.IsImport) if (!baseObj.TryGetValue("RowStruct", out var rowStructProp) || !(rowStructProp is ObjectProperty rowStruct) || !rowStruct.Value.IsImport)
{ {
return; return;
} }
var rowStructimportIndex = rowStruct.Value.AsImport; var rowStructimportIndex = rowStruct.Value.AsImport;
if (rowStructimportIndex >= reader.ImportMap.Length) if (rowStructimportIndex >= reader.ImportMap.Length)
{ {
return; return;
} }
var rowStructimport = reader.ImportMap[rowStructimportIndex]; var rowStructimport = reader.ImportMap[rowStructimportIndex];
if (rowStructimport.Type != EType.ScriptImport || if (rowStructimport.Type != EType.ScriptImport ||
!Globals.GlobalData.ScriptObjectByGlobalId.TryGetValue(rowStructimport, out var rowStrucDesc) || !Globals.GlobalData.ScriptObjectByGlobalId.TryGetValue(rowStructimport, out var rowStrucDesc) ||
rowStrucDesc.Name.IsNone) rowStrucDesc.Name.IsNone)
@ -59,11 +56,13 @@ namespace FModel.PakReader.Parsers.Class
return; return;
} }
if (!Globals.TypeMappings.TryGetValue(rowStrucDesc.Name.String, out var rowProperties)) // this slows down icon generation
{ //bool hasStruct = Globals.Usmap.Schemas.Any(x => x.Name == rowStrucDesc.Name.String);
FConsole.AppendText($"{reader.Summary.Name.String} can't be parsed yet (RowType: {rowStrucDesc.Name.String})", FColors.Red, true); //if (!hasStruct)
return; //{
} // FConsole.AppendText($"{reader.Summary.Name.String} can't be parsed yet (RowType: {rowStrucDesc.Name.String})", FColors.Red, true);
// return;
//}
var NumRows = reader.ReadInt32(); var NumRows = reader.ReadInt32();
RowMap = new Dictionary<string, object>(); RowMap = new Dictionary<string, object>();
@ -79,7 +78,7 @@ namespace FModel.PakReader.Parsers.Class
RowName = $"{baseName}_NK{num++:00}"; RowName = $"{baseName}_NK{num++:00}";
} }
RowMap[RowName] = new UObject(reader, rowProperties, true, rowStrucDesc.Name.String); RowMap[RowName] = new UObject(reader, rowStrucDesc.Name.String, true);
} }
} }

View File

@ -12,63 +12,51 @@ namespace FModel.PakReader.Parsers.Class
{ {
private readonly Dictionary<string, object> Dict; private readonly Dictionary<string, object> Dict;
public UObject(IoPackageReader reader, IReadOnlyDictionary<int, PropertyInfo> properties, bool structFallback = false, string type = null) public UObject(IoPackageReader reader, string type, bool structFallback = false)
{ {
Dict = new Dictionary<string, object>(); Dict = new Dictionary<string, object>();
var header = new FUnversionedHeader(reader); var header = new FUnversionedHeader(reader);
if (header.HasValues)
if (!header.HasValues)
{ {
if (!structFallback && reader.ReadInt32() != 0 /* && reader.Position + 16 <= maxSize*/) FUnversionedType unversionedType = reader.GetOrCreateSchema(type);
reader.Position += FGuid.SIZE; using var it = new FIterator(header);
if (header.HasNonZeroValues)
return; {
} var num = 1;
do
using var it = new FIterator(header); {
var (val, isNonZero) = it.Current;
if (unversionedType.Properties.TryGetValue(val, out var props))
{
var propertyTag = new FPropertyTag(props);
if (isNonZero)
{
var key = Dict.ContainsKey(props.Name) ? $"{props.Name}_NK{num++:00}" : props.Name;
var obj = BaseProperty.ReadAsObject(reader, propertyTag, propertyTag.Type, ReadType.NORMAL);
Dict[key] = obj;
}
else
{
var key = Dict.ContainsKey(props.Name) ? $"{props.Name}_NK{num++:00}" : props.Name;
var obj = BaseProperty.ReadAsZeroObject(reader, propertyTag, propertyTag.Type);
Dict[key] = obj;
}
}
else Dict[val.ToString()] = null;
} while (it.MoveNext());
}
else
{
#if DEBUG #if DEBUG
var headerWritten = false;
do
{
if (properties.ContainsKey(it.Current.Val))
continue;
if (!headerWritten)
{
headerWritten = true;
FConsole.AppendText(string.Concat("\n", type ?? "Unknown", ": ", reader.Summary.Name.String), "#CA6C6C", true); FConsole.AppendText(string.Concat("\n", type ?? "Unknown", ": ", reader.Summary.Name.String), "#CA6C6C", true);
} do
{
FConsole.AppendText($"Val: {it.Current.Val} (IsNonZero: {it.Current.IsNonZero})", FColors.Yellow, true); FConsole.AppendText($"Val: {it.Current.Val} (IsNonZero: {it.Current.IsNonZero})", FColors.Yellow, true);
} }
while (it.MoveNext()); while (it.MoveNext());
it.Reset();
#endif #endif
var num = 1;
do
{
var (val, isNonZero) = it.Current;
if (properties.TryGetValue(val, out var propertyInfo))
{
if (isNonZero)
{
var key = Dict.ContainsKey(propertyInfo.Name) ? $"{propertyInfo.Name}_NK{num++:00}" : propertyInfo.Name;
var obj = BaseProperty.ReadAsObject(reader, new FPropertyTag(propertyInfo), new FName(propertyInfo.Type), ReadType.NORMAL);
Dict[key] = obj;
}
else
{
var obj = BaseProperty.ReadAsZeroObject(reader, new FPropertyTag(propertyInfo), new FName(propertyInfo.Type));
var key = Dict.ContainsKey(propertyInfo.Name) ? $"{propertyInfo.Name}_NK{num++:00}" : propertyInfo.Name;
Dict[key] = obj;
}
} }
else Dict[val.ToString()] = null; }
} while (it.MoveNext());
if (!structFallback && reader.ReadInt32() != 0 /* && reader.Position + 16 <= maxSize*/) if (!structFallback && reader.ReadInt32() != 0 /* && reader.Position + 16 <= maxSize*/)
reader.Position += FGuid.SIZE; reader.Position += FGuid.SIZE;

View File

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FModel.PakReader.IO;
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;
using FModel.PakReader.Parsers.PropertyTagData; using FModel.PakReader.Parsers.PropertyTagData;
@ -53,8 +51,7 @@ namespace FModel.PakReader.Parsers.Class
} }
} }
internal USoundWave(IoPackageReader reader, Dictionary<int, PropertyInfo> properties, Stream ubulk, internal USoundWave(IoPackageReader reader, string type, Stream ubulk, long ubulkOffset) : base(reader, type)
long ubulkOffset) : base(reader, properties)
{ {
Serialize(reader, ubulk, ubulkOffset); Serialize(reader, ubulk, ubulkOffset);
} }

View File

@ -1,6 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using FModel.PakReader.IO;
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;
using FModel.PakReader.Textures; using FModel.PakReader.Textures;
using SkiaSharp; using SkiaSharp;
@ -50,8 +49,7 @@ namespace FModel.PakReader.Parsers.Class
} }
} }
internal UTexture2D(IoPackageReader reader, Dictionary<int, PropertyInfo> properties, Stream ubulk, internal UTexture2D(IoPackageReader reader, string type, Stream ubulk, long bulkOffset) : base(reader, type)
long bulkOffset) : base(reader, properties)
{ {
Serialize(reader, ubulk, bulkOffset); Serialize(reader, ubulk, bulkOffset);
} }

View File

@ -8,6 +8,7 @@ using FModel.PakReader.IO;
using FModel.PakReader.Parsers.Class; using FModel.PakReader.Parsers.Class;
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;
using FModel.Utils; using FModel.Utils;
using UsmapNET.Classes;
namespace FModel.PakReader.Parsers namespace FModel.PakReader.Parsers
{ {
@ -159,36 +160,16 @@ namespace FModel.PakReader.Parsers
_dataExportTypes[i] = exportType; _dataExportTypes[i] = exportType;
try try
{ {
if (Globals.TypeMappings.TryGetValue(exportType.String, out var properties)) _dataExports[i] = exportType.String switch
{ {
_dataExports[i] = exportType.String switch "Texture2D" => new UTexture2D(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
{ "TextureCube" => new UTexture2D(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
"Texture2D" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset), "VirtualTexture2D" => new UTexture2D(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
"TextureCube" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset), "CurveTable" => new UCurveTable(this, exportType.String),
"VirtualTexture2D" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset), "DataTable" => new UDataTable(this, exportType.String),
"CurveTable" => new UCurveTable(this), "SoundWave" => new USoundWave(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
"DataTable" => new UDataTable(this, properties, exportType.String), _ => new UObject(this, exportType.String, structFallback),
"SoundWave" => new USoundWave(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset), };
_ => new UObject(this, properties, structFallback, exportType.String),
};
}
else
{
_dataExports[i] = new UObject();
#if DEBUG
var header = new FUnversionedHeader(this);
if (!header.HasValues)
continue;
using var it = new FIterator(header);
FConsole.AppendText(string.Concat("\n", exportType.String, ": ", Summary.Name.String), "#CA6C6C", true);
do
{
FConsole.AppendText($"Val: {it.Current.Val} (IsNonZero: {it.Current.IsNonZero})", FColors.Yellow, true);
}
while (it.MoveNext());
#endif
}
} }
catch (Exception e) catch (Exception e)
{ {
@ -203,6 +184,45 @@ namespace FModel.PakReader.Parsers
public override string ToString() => Summary.Name.String; public override string ToString() => Summary.Name.String;
public FUnversionedType GetOrCreateSchema(string export)
{
if (Globals.CachedSchemas.TryGetValue(export, out var v))
{
return v;
}
else
{
var type = export;
var bNested = false;
var bNop = false;
var ret = new FUnversionedType(type);
while (type != null)
{
var schema = Globals.Usmap.Schemas.FirstOrDefault(x => x.Name == type);
if (schema.Name != null)
{
var lastIndex = ret.Properties.LastOrDefault().Key;
if (!bNop && (bNested && schema.PropCount > 0)) lastIndex++;
foreach (var prop in schema.Properties)
{
for (int i = 0; i < prop.ArraySize; i++)
{
ret.Properties[lastIndex + i + prop.SchemaIdx] = new FUnversionedProperty(prop);
}
}
bNop = !bNested && schema.PropCount == 0;
bNested = true;
type = schema.SuperType;
}
}
Globals.CachedSchemas[export] = ret;
return ret;
}
}
private string Transform(string path) private string Transform(string path)
{ {
string gname = Folders.GetGameName(); string gname = Folders.GetGameName();

View File

@ -1,4 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using UsmapNET.Classes;
namespace FModel.PakReader.Parsers.Objects namespace FModel.PakReader.Parsers.Objects
{ {
@ -23,6 +24,13 @@ namespace FModel.PakReader.Parsers.Objects
Number = number; Number = number;
} }
public FName(UsmapPropertyData name, int index = 0, int number = 0)
{
String = name != null ? name.Type.ToString() : "None";
Index = index;
Number = number;
}
public FName(string name, int index = 0, int number = 0) public FName(string name, int index = 0, int number = 0)
{ {
String = name; String = name;

View File

@ -21,16 +21,27 @@ namespace FModel.PakReader.Parsers.Objects
public readonly FName Type; // Variables public readonly FName Type; // Variables
public readonly FName ValueType; public readonly FName ValueType;
public FPropertyTag(PropertyInfo info) public FPropertyTag(FUnversionedProperty info)
{ {
BoolVal = 0;
Name = new FName(info.Name); Name = new FName(info.Name);
Type = new FName(info.Type); Type = new FName(info.Data);
StructName = new FName(info.StructType); StructName = new FName(info.Data.StructType);
BoolVal = (byte) ((info.Bool ?? false) ? 1 : 0); EnumName = new FName(info.Data.EnumName);
EnumName = new FName(info.EnumName); EnumType = new FName(info.Data.InnerType);
EnumType = new FName(info.EnumType); InnerType = new FName(info.Data.InnerType);
InnerType = new FName(info.InnerType); ValueType = new FName(info.Data.ValueType);
ValueType = new FName(info.ValueType);
if (InnerType.String == "StructProperty")
{
StructName = new FName(info.Data.InnerType.StructType);
}
else if (ValueType.String == "StructProperty")
{
StructName = new FName(info.Data.ValueType.StructType);
}
ArrayIndex = 0; ArrayIndex = 0;
Position = 0; Position = 0;
HasPropertyGuid = 0; HasPropertyGuid = 0;

View File

@ -1,7 +1,4 @@
using System.Collections.Generic; using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
using FModel.PakReader.IO;
using FModel.PakReader.Parsers.Class; using FModel.PakReader.Parsers.Class;
namespace FModel.PakReader.Parsers.Objects namespace FModel.PakReader.Parsers.Objects
@ -121,7 +118,7 @@ namespace FModel.PakReader.Parsers.Objects
{ {
if (reader is IoPackageReader ioReader) if (reader is IoPackageReader ioReader)
{ {
return Globals.TypeMappings.TryGetValue(structName, out var structProperties) ? new UObject(ioReader, structProperties, true, structName) : new UObject(ioReader, new Dictionary<int, PropertyInfo>(), true, structName); return new UObject(ioReader, structName, true);
} }
return new UObject(reader, true); return new UObject(reader, true);

View File

@ -1,4 +1,5 @@
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;
using System.Linq;
namespace FModel.PakReader.Parsers.PropertyTagData namespace FModel.PakReader.Parsers.PropertyTagData
{ {
@ -11,7 +12,6 @@ namespace FModel.PakReader.Parsers.PropertyTagData
internal EnumProperty(PackageReader reader, FPropertyTag tag, ReadType readType) internal EnumProperty(PackageReader reader, FPropertyTag tag, ReadType readType)
{ {
Position = reader.Position; Position = reader.Position;
if (!(reader is IoPackageReader) || readType != ReadType.NORMAL) if (!(reader is IoPackageReader) || readType != ReadType.NORMAL)
{ {
Value = reader.ReadFName(); Value = reader.ReadFName();
@ -23,23 +23,16 @@ namespace FModel.PakReader.Parsers.PropertyTagData
} }
} }
private static string ByteToEnum(string enumName, int value) private static string ByteToEnum(string enumName, int index)
{ {
if (enumName == null) if (enumName == null)
return value.ToString(); return index.ToString();
string result; var enumProp = Globals.Usmap.Enums.FirstOrDefault(x => x.Name == enumName);
if (!enumProp.Equals(default))
if (Globals.EnumMappings.TryGetValue(enumName, out var values)) return index >= enumProp.Names.Length ? string.Concat(enumName, "::", index) : string.Concat(enumName, "::", enumProp.Names[index]);
{
result = values.TryGetValue(value, out var member) ? string.Concat(enumName, "::", member) : string.Concat(enumName, "::", value);
}
else else
{ return string.Concat(enumName, "::", index);
result = string.Concat(enumName, "::", value);
}
return result;
} }
public string GetValue() => Value.String; public string GetValue() => Value.String;

View File

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using FModel.PakReader.Parsers.Objects; using FModel.PakReader.Parsers.Objects;

View File

@ -13,7 +13,7 @@ namespace FModel.PakReader.Parsers.PropertyTagData
{ {
Position = reader.Position; Position = reader.Position;
Value = new FSoftObjectPath(reader); Value = new FSoftObjectPath(reader);
if (readType == ReadType.MAP) if (!(reader is IoPackageReader) && readType == ReadType.MAP)
reader.Position += 16 - (reader.Position - Position); // skip ahead, putting the total bytes read to 16 reader.Position += 16 - (reader.Position - Position); // skip ahead, putting the total bytes read to 16
} }

View File

@ -14,9 +14,8 @@ namespace FModel.Utils
static class Endpoints static class Endpoints
{ {
public static readonly FortniteApi FortniteAPI = new FortniteApi($"FModel/{Assembly.GetExecutingAssembly().GetName().Version}"); public static readonly FortniteApi FortniteAPI = new FortniteApi($"FModel/{Assembly.GetExecutingAssembly().GetName().Version}");
public const string FORTNITE_TYPE_MAPPINGS = "https://raw.githubusercontent.com/FabianFG/FortniteTypeMappings/master/TypeMappings.json";
public const string FORTNITE_ENUM_MAPPINGS = "https://raw.githubusercontent.com/FabianFG/FortniteTypeMappings/master/EnumMappings.json";
public const string BENBOT_AES = "https://benbotfn.tk/api/v1/aes"; public const string BENBOT_AES = "https://benbotfn.tk/api/v1/aes";
public const string BENBOT_MAPPINGS = "https://benbotfn.tk/api/v1/mappings";
public const string BENBOT_HOTFIXES = "https://benbotfn.tk/api/v1/hotfixes"; public const string BENBOT_HOTFIXES = "https://benbotfn.tk/api/v1/hotfixes";
public const string FMODEL_JSON = "https://dl.dropbox.com/s/sxyaqo6zu1drlea/FModel.json?dl=0"; public const string FMODEL_JSON = "https://dl.dropbox.com/s/sxyaqo6zu1drlea/FModel.json?dl=0";
public const string OAUTH_URL = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/token"; public const string OAUTH_URL = "https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/token";
@ -25,17 +24,15 @@ namespace FModel.Utils
public static byte[] GetRawData(Uri uri) => GetRawDataAsync(uri).GetAwaiter().GetResult(); public static byte[] GetRawData(Uri uri) => GetRawDataAsync(uri).GetAwaiter().GetResult();
public static async Task<byte[]> GetRawDataAsync(Uri uri) public static async Task<byte[]> GetRawDataAsync(Uri uri)
{ {
using (HttpClient client = new HttpClient { Timeout = TimeSpan.FromSeconds(2) }) using HttpClient client = new HttpClient { Timeout = TimeSpan.FromSeconds(2) };
try
{ {
try var data = await client.GetByteArrayAsync(uri).ConfigureAwait(false);
{ return data;
var data = await client.GetByteArrayAsync(uri).ConfigureAwait(false); }
return data; catch
} {
catch return null;
{
return null;
}
} }
} }