mirror of
https://github.com/4sval/FModel.git
synced 2026-03-22 01:34:37 -05:00
implemented usmap
This commit is contained in:
parent
d05bed14a4
commit
841e76d2d7
|
|
@ -1,18 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29806.167
|
||||
VisualStudioVersion = 16.0.30804.86
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel\FModel.csproj", "{A42F8737-D056-4FA5-BEB5-AA96E1639F8A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
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.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.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
|
|
@ -20,6 +24,6 @@ Global
|
|||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {FE6EA91D-BBB8-4FBC-875C-25AD92EDB519}
|
||||
SolutionGuid = {688BAB53-42F7-45F2-AFDF-79A07771213F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@
|
|||
<PackageReference Include="System.Data.HashFunction.CityHash" Version="2.0.0" />
|
||||
<PackageReference Include="ToastNotifications" 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" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using FModel.Properties;
|
|||
using ToastNotifications;
|
||||
using ToastNotifications.Lifetime;
|
||||
using ToastNotifications.Position;
|
||||
using UsmapNET.Classes;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
|
|
@ -19,9 +20,9 @@ namespace FModel
|
|||
/// </summary>
|
||||
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, FUnversionedType> CachedSchemas = new Dictionary<string, FUnversionedType>();
|
||||
public static Usmap Usmap = 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 =>
|
||||
{
|
||||
cfg.LifetimeSupervisor = new TimeAndCountBasedLifetimeSupervisor(TimeSpan.FromSeconds(7), MaximumNotificationCount.FromCount(15));
|
||||
|
|
|
|||
50
FModel/Grabber/Mappings/MappingsData.cs
Normal file
50
FModel/Grabber/Mappings/MappingsData.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
45
FModel/Grabber/Mappings/MappingsGrabber.cs
Normal file
45
FModel/Grabber/Mappings/MappingsGrabber.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,19 +23,15 @@ using FModel.Windows.Search;
|
|||
using FModel.Windows.Settings;
|
||||
using FModel.Windows.SoundPlayer;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System.Net.NetworkInformation;
|
||||
using FModel.Grabber.Mappings;
|
||||
|
||||
namespace FModel
|
||||
{
|
||||
|
|
@ -83,7 +79,6 @@ namespace FModel
|
|||
Keys.NoKeyGoodBye();
|
||||
MenuItems.FeedCustomGoTos();
|
||||
AeConfiguration();
|
||||
LoadMappings();
|
||||
|
||||
if (t.Exception != null) Tasks.TaskCompleted(t.Exception);
|
||||
else StatusBarVm.statusBarViewModel.Set($"{Properties.Resources.Hello} {Environment.UserName}!", Properties.Resources.State);
|
||||
|
|
@ -98,54 +93,22 @@ namespace FModel
|
|||
{
|
||||
await PaksGrabber.PopulateMenu().ConfigureAwait(false);
|
||||
await AesGrabber.Load(Properties.Settings.Default.ReloadAesKeys).ConfigureAwait(false);
|
||||
await MappingsGrabber.Load().ConfigureAwait(false);
|
||||
await CdnDataGrabber.DoCDNStuff().ConfigureAwait(false);
|
||||
await Folders.DownloadAndExtractVgm().ConfigureAwait(false);
|
||||
if (Properties.Settings.Default.UseDiscordRpc) DiscordIntegration.StartClient();
|
||||
}
|
||||
|
||||
private async void LoadMappings()
|
||||
public async void ReloadMappings(object sender, RoutedEventArgs e)
|
||||
{
|
||||
string rawMappings = "{}";
|
||||
string rawEnumMappings = "{}";
|
||||
|
||||
#if DEBUG
|
||||
if (File.Exists("TypeMappings.json"))
|
||||
if (await MappingsGrabber.Load(true).ConfigureAwait(false))
|
||||
{
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ namespace FModel.PakReader.IO
|
|||
public static bool operator ==(FIoDirectoryIndexHandle a, FIoDirectoryIndexHandle b) => a._handle == b._handle;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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)]
|
||||
public static FIoDirectoryIndexHandle FromIndex(uint index) => new FIoDirectoryIndexHandle(index);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ namespace FModel.PakReader.IO
|
|||
{
|
||||
_zeroMask = header.ZeroMask;
|
||||
_fragmentIt = header.Fragments.GetEnumerator();
|
||||
if (header.HasValues)
|
||||
Skip();
|
||||
Skip();
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
|
|
|
|||
29
FModel/PakReader/IO/FUnversionedProperty.cs
Normal file
29
FModel/PakReader/IO/FUnversionedProperty.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FModel.PakReader.IO;
|
||||
using FModel.PakReader.Parsers.Objects;
|
||||
|
||||
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.ReadUInt32(); // what this is
|
||||
|
||||
int NumRows = reader.ReadInt32();
|
||||
CurveTableMode = (ECurveTableMode)reader.ReadByte();
|
||||
Dictionary<int, PropertyInfo> properties = CurveTableMode switch
|
||||
|
||||
string export = CurveTableMode switch
|
||||
{
|
||||
ECurveTableMode.RichCurves => Globals.TypeMappings["RichCurve"],
|
||||
ECurveTableMode.SimpleCurves => Globals.TypeMappings["SimpleCurve"],
|
||||
ECurveTableMode.RichCurves => "RichCurve",
|
||||
ECurveTableMode.SimpleCurves => "SimpleCurve",
|
||||
_ => throw new FileLoadException($"This table has an unknown mode ({CurveTableMode})")
|
||||
};
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ namespace FModel.PakReader.Parsers.Class
|
|||
RowName = $"{baseName}_NK{num++:00}";
|
||||
}
|
||||
|
||||
RowMap[RowName] = new UObject(reader, properties, true);
|
||||
RowMap[RowName] = new UObject(reader, export, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using FModel.PakReader.IO;
|
||||
using FModel.PakReader.Parsers.PropertyTagData;
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rowStructimportIndex = rowStruct.Value.AsImport;
|
||||
|
||||
if (rowStructimportIndex >= reader.ImportMap.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var rowStructimport = reader.ImportMap[rowStructimportIndex];
|
||||
|
||||
if (rowStructimport.Type != EType.ScriptImport ||
|
||||
!Globals.GlobalData.ScriptObjectByGlobalId.TryGetValue(rowStructimport, out var rowStrucDesc) ||
|
||||
rowStrucDesc.Name.IsNone)
|
||||
|
|
@ -59,11 +56,13 @@ namespace FModel.PakReader.Parsers.Class
|
|||
return;
|
||||
}
|
||||
|
||||
if (!Globals.TypeMappings.TryGetValue(rowStrucDesc.Name.String, out var rowProperties))
|
||||
{
|
||||
FConsole.AppendText($"{reader.Summary.Name.String} can't be parsed yet (RowType: {rowStrucDesc.Name.String})", FColors.Red, true);
|
||||
return;
|
||||
}
|
||||
// this slows down icon generation
|
||||
//bool hasStruct = Globals.Usmap.Schemas.Any(x => x.Name == rowStrucDesc.Name.String);
|
||||
//if (!hasStruct)
|
||||
//{
|
||||
// FConsole.AppendText($"{reader.Summary.Name.String} can't be parsed yet (RowType: {rowStrucDesc.Name.String})", FColors.Red, true);
|
||||
// return;
|
||||
//}
|
||||
|
||||
var NumRows = reader.ReadInt32();
|
||||
RowMap = new Dictionary<string, object>();
|
||||
|
|
@ -79,7 +78,7 @@ namespace FModel.PakReader.Parsers.Class
|
|||
RowName = $"{baseName}_NK{num++:00}";
|
||||
}
|
||||
|
||||
RowMap[RowName] = new UObject(reader, rowProperties, true, rowStrucDesc.Name.String);
|
||||
RowMap[RowName] = new UObject(reader, rowStrucDesc.Name.String, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,63 +12,51 @@ namespace FModel.PakReader.Parsers.Class
|
|||
{
|
||||
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>();
|
||||
var header = new FUnversionedHeader(reader);
|
||||
|
||||
if (!header.HasValues)
|
||||
if (header.HasValues)
|
||||
{
|
||||
if (!structFallback && reader.ReadInt32() != 0 /* && reader.Position + 16 <= maxSize*/)
|
||||
reader.Position += FGuid.SIZE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
using var it = new FIterator(header);
|
||||
|
||||
FUnversionedType unversionedType = reader.GetOrCreateSchema(type);
|
||||
using var it = new FIterator(header);
|
||||
if (header.HasNonZeroValues)
|
||||
{
|
||||
var num = 1;
|
||||
do
|
||||
{
|
||||
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
|
||||
|
||||
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($"Val: {it.Current.Val} (IsNonZero: {it.Current.IsNonZero})", FColors.Yellow, true);
|
||||
}
|
||||
while (it.MoveNext());
|
||||
it.Reset();
|
||||
do
|
||||
{
|
||||
FConsole.AppendText($"Val: {it.Current.Val} (IsNonZero: {it.Current.IsNonZero})", FColors.Yellow, true);
|
||||
}
|
||||
while (it.MoveNext());
|
||||
#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*/)
|
||||
reader.Position += FGuid.SIZE;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FModel.PakReader.IO;
|
||||
using FModel.PakReader.Parsers.Objects;
|
||||
using FModel.PakReader.Parsers.PropertyTagData;
|
||||
|
||||
|
|
@ -53,8 +51,7 @@ namespace FModel.PakReader.Parsers.Class
|
|||
}
|
||||
}
|
||||
|
||||
internal USoundWave(IoPackageReader reader, Dictionary<int, PropertyInfo> properties, Stream ubulk,
|
||||
long ubulkOffset) : base(reader, properties)
|
||||
internal USoundWave(IoPackageReader reader, string type, Stream ubulk, long ubulkOffset) : base(reader, type)
|
||||
{
|
||||
Serialize(reader, ubulk, ubulkOffset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using FModel.PakReader.IO;
|
||||
using FModel.PakReader.Parsers.Objects;
|
||||
using FModel.PakReader.Textures;
|
||||
using SkiaSharp;
|
||||
|
|
@ -50,8 +49,7 @@ namespace FModel.PakReader.Parsers.Class
|
|||
}
|
||||
}
|
||||
|
||||
internal UTexture2D(IoPackageReader reader, Dictionary<int, PropertyInfo> properties, Stream ubulk,
|
||||
long bulkOffset) : base(reader, properties)
|
||||
internal UTexture2D(IoPackageReader reader, string type, Stream ubulk, long bulkOffset) : base(reader, type)
|
||||
{
|
||||
Serialize(reader, ubulk, bulkOffset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using FModel.PakReader.IO;
|
|||
using FModel.PakReader.Parsers.Class;
|
||||
using FModel.PakReader.Parsers.Objects;
|
||||
using FModel.Utils;
|
||||
using UsmapNET.Classes;
|
||||
|
||||
namespace FModel.PakReader.Parsers
|
||||
{
|
||||
|
|
@ -159,36 +160,16 @@ namespace FModel.PakReader.Parsers
|
|||
_dataExportTypes[i] = exportType;
|
||||
try
|
||||
{
|
||||
if (Globals.TypeMappings.TryGetValue(exportType.String, out var properties))
|
||||
_dataExports[i] = exportType.String switch
|
||||
{
|
||||
_dataExports[i] = exportType.String switch
|
||||
{
|
||||
"Texture2D" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
|
||||
"TextureCube" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
|
||||
"VirtualTexture2D" => new UTexture2D(this, properties, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
|
||||
"CurveTable" => new UCurveTable(this),
|
||||
"DataTable" => new UDataTable(this, properties, exportType.String),
|
||||
"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
|
||||
}
|
||||
"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),
|
||||
"VirtualTexture2D" => new UTexture2D(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
|
||||
"CurveTable" => new UCurveTable(this, exportType.String),
|
||||
"DataTable" => new UDataTable(this, exportType.String),
|
||||
"SoundWave" => new USoundWave(this, exportType.String, _ubulk, ExportMap.Sum(e => (long)e.CookedSerialSize) + beginExportOffset),
|
||||
_ => new UObject(this, exportType.String, structFallback),
|
||||
};
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -203,6 +184,45 @@ namespace FModel.PakReader.Parsers
|
|||
|
||||
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)
|
||||
{
|
||||
string gname = Folders.GetGameName();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Newtonsoft.Json;
|
||||
using UsmapNET.Classes;
|
||||
|
||||
namespace FModel.PakReader.Parsers.Objects
|
||||
{
|
||||
|
|
@ -23,6 +24,13 @@ namespace FModel.PakReader.Parsers.Objects
|
|||
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)
|
||||
{
|
||||
String = name;
|
||||
|
|
|
|||
|
|
@ -21,16 +21,27 @@ namespace FModel.PakReader.Parsers.Objects
|
|||
public readonly FName Type; // Variables
|
||||
public readonly FName ValueType;
|
||||
|
||||
public FPropertyTag(PropertyInfo info)
|
||||
public FPropertyTag(FUnversionedProperty info)
|
||||
{
|
||||
BoolVal = 0;
|
||||
|
||||
Name = new FName(info.Name);
|
||||
Type = new FName(info.Type);
|
||||
StructName = new FName(info.StructType);
|
||||
BoolVal = (byte) ((info.Bool ?? false) ? 1 : 0);
|
||||
EnumName = new FName(info.EnumName);
|
||||
EnumType = new FName(info.EnumType);
|
||||
InnerType = new FName(info.InnerType);
|
||||
ValueType = new FName(info.ValueType);
|
||||
Type = new FName(info.Data);
|
||||
StructName = new FName(info.Data.StructType);
|
||||
EnumName = new FName(info.Data.EnumName);
|
||||
EnumType = new FName(info.Data.InnerType);
|
||||
InnerType = new FName(info.Data.InnerType);
|
||||
ValueType = new FName(info.Data.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;
|
||||
Position = 0;
|
||||
HasPropertyGuid = 0;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using FModel.PakReader.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using FModel.PakReader.Parsers.Class;
|
||||
|
||||
namespace FModel.PakReader.Parsers.Objects
|
||||
|
|
@ -121,7 +118,7 @@ namespace FModel.PakReader.Parsers.Objects
|
|||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using FModel.PakReader.Parsers.Objects;
|
||||
using System.Linq;
|
||||
|
||||
namespace FModel.PakReader.Parsers.PropertyTagData
|
||||
{
|
||||
|
|
@ -11,7 +12,6 @@ namespace FModel.PakReader.Parsers.PropertyTagData
|
|||
internal EnumProperty(PackageReader reader, FPropertyTag tag, ReadType readType)
|
||||
{
|
||||
Position = reader.Position;
|
||||
|
||||
if (!(reader is IoPackageReader) || readType != ReadType.NORMAL)
|
||||
{
|
||||
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)
|
||||
return value.ToString();
|
||||
return index.ToString();
|
||||
|
||||
string result;
|
||||
|
||||
if (Globals.EnumMappings.TryGetValue(enumName, out var values))
|
||||
{
|
||||
result = values.TryGetValue(value, out var member) ? string.Concat(enumName, "::", member) : string.Concat(enumName, "::", value);
|
||||
}
|
||||
var enumProp = Globals.Usmap.Enums.FirstOrDefault(x => x.Name == enumName);
|
||||
if (!enumProp.Equals(default))
|
||||
return index >= enumProp.Names.Length ? string.Concat(enumName, "::", index) : string.Concat(enumName, "::", enumProp.Names[index]);
|
||||
else
|
||||
{
|
||||
result = string.Concat(enumName, "::", value);
|
||||
}
|
||||
|
||||
return result;
|
||||
return string.Concat(enumName, "::", index);
|
||||
}
|
||||
|
||||
public string GetValue() => Value.String;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FModel.PakReader.Parsers.Objects;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace FModel.PakReader.Parsers.PropertyTagData
|
|||
{
|
||||
Position = reader.Position;
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,8 @@ namespace FModel.Utils
|
|||
static class Endpoints
|
||||
{
|
||||
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_MAPPINGS = "https://benbotfn.tk/api/v1/mappings";
|
||||
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 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 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;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var data = await client.GetByteArrayAsync(uri).ConfigureAwait(false);
|
||||
return data;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user