mirror of
https://github.com/AssetRipper/Tpk.git
synced 2026-11-13 18:07:47 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94549d10ee | ||
|
|
1a2c247668 | ||
|
|
f94757d204 | ||
|
|
474fe30489 | ||
|
|
70c3b6ca93 | ||
|
|
6b72bf855d | ||
|
|
be9d53f317 | ||
|
|
a7e3d89b2d | ||
|
|
21eca606fd | ||
|
|
8bef636a8f | ||
|
|
7ed791b58c | ||
|
|
236236fed8 | ||
|
|
019d733bb2 | ||
|
|
7663a53449 | ||
|
|
f9e25d911f | ||
|
|
a4f6013e45 | ||
|
|
1b0a2b3082 | ||
|
|
b5b5ace321 | ||
|
|
b899a92602 | ||
|
|
c07faa29d5 | ||
|
|
066c28f93e | ||
|
|
a9014885b5 | ||
|
|
1e52aabbba | ||
|
|
5fa4cb3aec | ||
|
|
742bfd10c7 | ||
|
|
85a195481f | ||
|
|
0848676272 | ||
|
|
ef5f006d86 | ||
|
|
63ae06b81c | ||
|
|
0346ab5638 | ||
|
|
7b0d976098 | ||
|
|
78795b0f3b | ||
|
|
631e16635c | ||
|
|
7c12284938 | ||
|
|
3a92e1500d | ||
|
|
da9deb5c43 | ||
|
|
03866b2bd6 | ||
|
|
d3d2280b17 | ||
|
|
43c367d0aa | ||
|
|
04979752a5 | ||
|
|
5954d55e23 | ||
|
|
2eaaef50da | ||
|
|
488e212e16 | ||
|
|
24da9dda10 | ||
|
|
46e3867d3c | ||
|
|
6bdc11a7cb | ||
|
|
e7c20cfdd1 | ||
|
|
7eef5f06d1 | ||
|
|
8c6d9c46be | ||
|
|
1636b8a896 | ||
|
|
4a92302463 |
No files matched your search
@@ -1,63 +0,0 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
@@ -27,45 +27,45 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Tpk Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v6
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 10.0.x
|
||||
- name: Build
|
||||
run: dotnet build /p:Configuration=Release
|
||||
working-directory: ./Tpk.ConsoleApp/
|
||||
- name: Checkout DocumentationDumps Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
repository: 'AssetRipper/DocumentationDumps'
|
||||
path: DocumentationDumps
|
||||
- name: Make files executable
|
||||
shell: bash
|
||||
run: chmod +x ./Tpk.ConsoleApp/bin/Release/net6.0/AssetRipper.Tpk.ConsoleApp
|
||||
run: chmod +x ./Tpk.ConsoleApp/bin/Release/net10.0/AssetRipper.Tpk.ConsoleApp
|
||||
- name: Make tpk file
|
||||
shell: bash
|
||||
run: ./Tpk.ConsoleApp/bin/Release/net6.0/AssetRipper.Tpk.ConsoleApp --engine-assets ./DocumentationDumps/EngineAssets
|
||||
run: ./Tpk.ConsoleApp/bin/Release/net10.0/AssetRipper.Tpk.ConsoleApp --engine-assets ./DocumentationDumps/EngineAssets
|
||||
- name: Upload Uncompressed file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: uncompressed_file
|
||||
path: ./uncompressed.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Lz4 file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: lz4_file
|
||||
path: ./lz4.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Lzma file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: lzma_file
|
||||
path: ./lzma.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Brotli file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: brotli_file
|
||||
path: ./brotli.tpk
|
||||
|
||||
@@ -12,11 +12,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v7
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v6
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 10.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
|
||||
@@ -27,47 +27,48 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Tpk Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
uses: actions/setup-dotnet@v6
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 10.0.x
|
||||
- name: Build
|
||||
run: dotnet build /p:Configuration=Release
|
||||
working-directory: ./Tpk.ConsoleApp/
|
||||
- name: Checkout TypeTreeDumps Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
repository: 'AssetRipper/TypeTreeDumps'
|
||||
sparse-checkout: 'InfoJson'
|
||||
path: TypeTreeDumps
|
||||
- name: Make files executable
|
||||
shell: bash
|
||||
run: chmod +x ./Tpk.ConsoleApp/bin/Release/net6.0/AssetRipper.Tpk.ConsoleApp
|
||||
run: chmod +x ./Tpk.ConsoleApp/bin/Release/net10.0/AssetRipper.Tpk.ConsoleApp
|
||||
- name: Make tpk file
|
||||
shell: bash
|
||||
run: ./Tpk.ConsoleApp/bin/Release/net6.0/AssetRipper.Tpk.ConsoleApp --type-tree ./TypeTreeDumps/InfoJson
|
||||
run: ./Tpk.ConsoleApp/bin/Release/net10.0/AssetRipper.Tpk.ConsoleApp --type-tree ./TypeTreeDumps/InfoJson
|
||||
- name: Upload Uncompressed file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: uncompressed_file
|
||||
path: ./uncompressed.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Lz4 file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: lz4_file
|
||||
path: ./lz4.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Lzma file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: lzma_file
|
||||
path: ./lzma.tpk
|
||||
if-no-files-found: error
|
||||
- name: Upload Brotli file
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: brotli_file
|
||||
path: ./brotli.tpk
|
||||
if-no-files-found: error
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAotCompatible>true</IsAotCompatible>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
|
||||
<Authors>ds5678</Authors>
|
||||
<Company>AssetRipper</Company>
|
||||
<VersionPrefix>2.0.0</VersionPrefix>
|
||||
<RepositoryUrl>https://github.com/AssetRipper/Tpk</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
<Copyright>Copyright (c) ds5678</Copyright>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -4,6 +4,8 @@ A tool for compressing [type tree dumps](https://github.com/AssetRipper/TypeTree
|
||||
|
||||
## Type Tree Tpk
|
||||
|
||||
> Warning: [AssetsTools.NET](https://github.com/nesrak1/AssetsTools.NET) does not support Brotli compression.
|
||||
|
||||
| Compression | Link |
|
||||
| ----------- | ---- |
|
||||
| [Brotli](https://nightly.link/AssetRipper/Tpk/workflows/type_tree_tpk/master/brotli_file) | https://nightly.link/AssetRipper/Tpk/workflows/type_tree_tpk/master/brotli_file.zip |
|
||||
@@ -13,6 +15,8 @@ A tool for compressing [type tree dumps](https://github.com/AssetRipper/TypeTree
|
||||
|
||||
## Engine Assets Tpk
|
||||
|
||||
> This is an internal file for AssetRipper and might not have much other use.
|
||||
|
||||
| Compression | Link |
|
||||
| ----------- | ---- |
|
||||
| [Brotli](https://nightly.link/AssetRipper/Tpk/workflows/engine_assets_tpk/master/brotli_file) | https://nightly.link/AssetRipper/Tpk/workflows/engine_assets_tpk/master/brotli_file.zip |
|
||||
|
||||
@@ -2,20 +2,13 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>AssetRipper.Tpk.ConsoleApp</RootNamespace>
|
||||
<AssemblyName>AssetRipper.Tpk.ConsoleApp</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Tpk.TypeTrees.Json\Tpk.TypeTrees.Json.csproj" />
|
||||
<ProjectReference Include="..\Tpk\Tpk.csproj" />
|
||||
<ProjectReference Include="..\Tpk.TypeTrees.Json\Tpk.TypeTrees.Json.csproj" />
|
||||
<ProjectReference Include="..\Tpk\Tpk.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,4 +1,5 @@
|
||||
using AssetRipper.Primitives;
|
||||
using AssetRipper.Tpk.Shared;
|
||||
using AssetRipper.Tpk.TypeTrees;
|
||||
using AssetRipper.Tpk.TypeTrees.Json;
|
||||
using System.Collections.Generic;
|
||||
@@ -28,44 +29,37 @@ namespace AssetRipper.Tpk.ConsoleApp
|
||||
|
||||
private static TpkTypeTreeBlob Create(IEnumerable<string> pathsOrderedByUnityVersion)
|
||||
{
|
||||
return Create(pathsOrderedByUnityVersion.Select(path => UnityInfo.ReadFromJsonFile(path)));
|
||||
return Create(pathsOrderedByUnityVersion.Select(path =>
|
||||
{
|
||||
string versionString = Path.GetFileNameWithoutExtension(path);
|
||||
UnityVersion version = UnityVersion.Parse(versionString);
|
||||
UnityInfo info = UnityInfo.ReadFromJsonFile(path);
|
||||
return (version, info);
|
||||
}));
|
||||
}
|
||||
|
||||
private static TpkTypeTreeBlob Create(IEnumerable<UnityInfo> infosOrderedByUnityVersion)
|
||||
private static TpkTypeTreeBlob Create(IEnumerable<(UnityVersion Version, UnityInfo Info)> infosOrderedByUnityVersion)
|
||||
{
|
||||
TpkTypeTreeBlob blob = new TpkTypeTreeBlob();
|
||||
blob.CommonString.Add(UnityVersion.MinVersion, 0);
|
||||
|
||||
byte latestCommonStringCount = 0;
|
||||
List<string> commonStrings = new List<string>();
|
||||
Dictionary<int, string> latestUnityClassesDumped = new Dictionary<int, string>();
|
||||
Dictionary<int, TpkClassInformation> classDictionary = new Dictionary<int, TpkClassInformation>();
|
||||
List<TpkCommonString.Entry> commonStrings = [];
|
||||
Dictionary<int, string> latestUnityClassesDumped = [];
|
||||
Dictionary<int, TpkClassInformation> classDictionary = [];
|
||||
|
||||
foreach (UnityInfo info in infosOrderedByUnityVersion)
|
||||
foreach ((UnityVersion version, UnityInfo? info) in infosOrderedByUnityVersion)
|
||||
{
|
||||
Console.WriteLine(info.Version);
|
||||
UnityVersion version = UnityVersion.Parse(info.Version);
|
||||
Console.WriteLine(version.ToString());
|
||||
blob.Versions.Add(version);
|
||||
|
||||
if (info.Strings.Count != latestCommonStringCount)
|
||||
if (!Same(info.Strings, commonStrings, blob.StringBuffer))
|
||||
{
|
||||
latestCommonStringCount = (byte)info.Strings.Count;
|
||||
blob.CommonString.Add(version, latestCommonStringCount);
|
||||
}
|
||||
|
||||
for (int i = 0; i < info.Strings.Count; i++)
|
||||
{
|
||||
if (i < commonStrings.Count)
|
||||
commonStrings.Clear();
|
||||
commonStrings.EnsureCapacity(commonStrings.Count);
|
||||
foreach (UnityString unityString in info.Strings)
|
||||
{
|
||||
if (info.Strings[i].String != commonStrings[i])
|
||||
{
|
||||
throw new Exception($"String inequality at index {i} for version {version}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
commonStrings.Add(info.Strings[i].String);
|
||||
commonStrings.Add(new TpkCommonString.Entry((ushort)unityString.Index, unityString.String, blob.StringBuffer));
|
||||
}
|
||||
blob.CommonString.Add(version, commonStrings.ToArray());
|
||||
}
|
||||
|
||||
foreach (UnityClass unityClass in info.Classes)
|
||||
@@ -115,8 +109,7 @@ namespace AssetRipper.Tpk.ConsoleApp
|
||||
|
||||
blob.ClassInformation.AddRange(classDictionary.Values);
|
||||
|
||||
blob.CommonString.SetIndices(blob.StringBuffer, commonStrings);
|
||||
//About 21k / 65k
|
||||
//About 26k / 65k
|
||||
Console.WriteLine($"Node buffer has {blob.NodeBuffer.Count} entries, which is {GetUShortPercent(blob.NodeBuffer.Count)}% of its maximum {ushort.MaxValue} entries");
|
||||
//About 7k / 65k
|
||||
Console.WriteLine($"String buffer has {blob.StringBuffer.Count} entries, which is {GetUShortPercent(blob.StringBuffer.Count)}% of its maximum {ushort.MaxValue} entries");
|
||||
@@ -126,6 +119,22 @@ namespace AssetRipper.Tpk.ConsoleApp
|
||||
return blob;
|
||||
}
|
||||
|
||||
private static bool Same(List<UnityString> jsonStrings, List<TpkCommonString.Entry> tpkEntries, TpkStringBuffer stringBuffer)
|
||||
{
|
||||
if (jsonStrings.Count != tpkEntries.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < jsonStrings.Count; i++)
|
||||
{
|
||||
if (jsonStrings[i].String != tpkEntries[i].ToString(stringBuffer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int GetUShortPercent(int value) => value * 100 / ushort.MaxValue;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using AssetRipper.Primitives;
|
||||
using AssetRipper.Tpk.TypeTrees.Json;
|
||||
using AssetRipper.Primitives;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Writers.Zip;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetRipper.Tpk.ConsoleApp
|
||||
{
|
||||
@@ -12,48 +14,32 @@ namespace AssetRipper.Tpk.ConsoleApp
|
||||
/// </summary>
|
||||
/// <param name="zipFilePath"></param>
|
||||
/// <returns>A list ordered by Unity version</returns>
|
||||
public static IEnumerable<UnityInfo> ReadUnityInfoFromZipFile(string zipFilePath)
|
||||
public static IEnumerable<(UnityVersion Version, UnityInfo Info)> ReadUnityInfoFromZipFile(string zipFilePath)
|
||||
{
|
||||
List<UnityInfo> list = new();
|
||||
List<(UnityVersion Version, UnityInfo Info)> list = new();
|
||||
|
||||
using FileStream fileStream = File.OpenRead(zipFilePath);
|
||||
using ZipInputStream zipInputStream = new ZipInputStream(fileStream);
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInputStream.GetNextEntry()) is not null)
|
||||
using IWritableArchive<ZipWriterOptions> archive = ZipArchive.OpenArchive(fileStream);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if(entry.IsFile && entry.Name.EndsWith(".json", StringComparison.Ordinal))
|
||||
if (!entry.IsDirectory && (entry.Key ?? "").EndsWith(".json", StringComparison.Ordinal))
|
||||
{
|
||||
string versionString = Path.GetFileNameWithoutExtension(entry.Key ?? "");
|
||||
UnityVersion version = UnityVersion.Parse(versionString);
|
||||
using MemoryStream unzippedFileStream = new MemoryStream();
|
||||
zipInputStream.CopyTo(unzippedFileStream);
|
||||
entry.WriteTo(unzippedFileStream);
|
||||
unzippedFileStream.Position = 0;
|
||||
UnityInfo? info = UnityInfo.FromStream(unzippedFileStream);
|
||||
if(info is not null)
|
||||
if (info is not null)
|
||||
{
|
||||
list.Add(info);
|
||||
list.Add((version, info));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.Sort(CompareUnityInfo);
|
||||
list.Sort((a, b) => a.Version.CompareTo(b.Version));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two UnityInfo by their versions
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
/// <returns>
|
||||
/// Less than zero: a precedes b<br />
|
||||
/// Zero: equivalent position<br />
|
||||
/// Greater than zero: a follows b
|
||||
/// </returns>
|
||||
private static int CompareUnityInfo(UnityInfo a, UnityInfo b)
|
||||
{
|
||||
UnityVersion versionA = UnityVersion.Parse(a.Version);
|
||||
UnityVersion versionB = UnityVersion.Parse(b.Version);
|
||||
return versionA.CompareTo(versionB);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,12 @@ public class EngineAssetsTests
|
||||
originalBlob.Data.Add(new KeyValuePair<UnityVersion, string>(new UnityVersion(4), RandomUtils.RandomString()));
|
||||
byte[] writtenData = originalBlob.ToBinary();
|
||||
TpkEngineAssetsBlob readBlob = TpkDataBlob.FromBinary<TpkEngineAssetsBlob>(writtenData);
|
||||
Assert.Multiple(() =>
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(readBlob.CreationTime, Is.EqualTo(originalBlob.CreationTime));
|
||||
Assert.That(readBlob.Versions, Is.EqualTo(originalBlob.Versions));
|
||||
Assert.That(readBlob.Data, Is.EqualTo(originalBlob.Data));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -33,11 +33,11 @@ public class EngineAssetsTests
|
||||
TpkEngineAssetsBlob originalBlob = new();
|
||||
byte[] writtenData = originalBlob.ToBinary();
|
||||
TpkEngineAssetsBlob readBlob = TpkDataBlob.FromBinary<TpkEngineAssetsBlob>(writtenData);
|
||||
Assert.Multiple(() =>
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(readBlob.CreationTime, Is.EqualTo(originalBlob.CreationTime));
|
||||
Assert.That(readBlob.Versions, Is.EqualTo(originalBlob.Versions));
|
||||
Assert.That(readBlob.Data, Is.EqualTo(originalBlob.Data));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>AssetRipper.Tpk.Tests</RootNamespace>
|
||||
<AssemblyName>AssetRipper.Tpk.Tests</AssemblyName>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
||||
<PackageReference Include="NUnit" Version="4.6.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.14.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace AssetRipper.Tpk.Tests
|
||||
{
|
||||
TpkFile file = CreateTpkFile();
|
||||
byte[] data = file.WriteToMemory();
|
||||
Assert.Multiple(() =>
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(data[0], Is.EqualTo((byte)'T'));
|
||||
Assert.That(data[1], Is.EqualTo((byte)'P'));
|
||||
Assert.That(data[2], Is.EqualTo((byte)'K'));
|
||||
Assert.That(data[3], Is.EqualTo((byte)'*'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static TpkFile CreateTpkFile()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using AssetRipper.Primitives;
|
||||
using AssetRipper.Tpk.TypeTrees;
|
||||
using NUnit.Framework;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetRipper.Tpk.Tests.TypeTrees
|
||||
{
|
||||
@@ -9,35 +10,54 @@ namespace AssetRipper.Tpk.Tests.TypeTrees
|
||||
private static UnityVersion Unity3 => new UnityVersion(3, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity4 => new UnityVersion(4, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity5 => new UnityVersion(5, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity6 => new UnityVersion(6, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity7 => new UnityVersion(7, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity6 => new UnityVersion(6000, 0, 0, UnityVersionType.Final, 1);
|
||||
private static UnityVersion Unity7 => new UnityVersion(7000, 0, 0, UnityVersionType.Final, 1);
|
||||
|
||||
[Test]
|
||||
public static void CountIsCorrectForEmptyCommonString()
|
||||
{
|
||||
TpkCommonString commonString = new();
|
||||
Assert.That(commonString.GetCount(Unity5), Is.EqualTo(0));
|
||||
Assert.That(commonString.GetEntries(Unity5), Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void CountIsCorrectForNormalUse()
|
||||
{
|
||||
TpkCommonString commonString = MakeCommonString();
|
||||
Assert.Multiple(() =>
|
||||
using (Assert.EnterMultipleScope())
|
||||
{
|
||||
Assert.That(commonString.GetCount(Unity3), Is.EqualTo(5));
|
||||
Assert.That(commonString.GetCount(Unity4), Is.EqualTo(5));
|
||||
Assert.That(commonString.GetCount(Unity5), Is.EqualTo(5));
|
||||
Assert.That(commonString.GetCount(Unity6), Is.EqualTo(10));
|
||||
Assert.That(commonString.GetCount(Unity7), Is.EqualTo(10));
|
||||
});
|
||||
Assert.That(commonString.GetEntries(Unity3), Has.Length.EqualTo(5));
|
||||
Assert.That(commonString.GetEntries(Unity4), Has.Length.EqualTo(5));
|
||||
Assert.That(commonString.GetEntries(Unity5), Has.Length.EqualTo(5));
|
||||
Assert.That(commonString.GetEntries(Unity6), Has.Length.EqualTo(10));
|
||||
Assert.That(commonString.GetEntries(Unity7), Has.Length.EqualTo(10));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void ReadingAndWritingUseSameBytes()
|
||||
{
|
||||
TpkCommonString commonString = MakeCommonString();
|
||||
MemoryStream stream = new();
|
||||
BinaryWriter writer = new(stream);
|
||||
commonString.Write(writer);
|
||||
writer.Flush();
|
||||
int bytesWritten = (int)stream.Length;
|
||||
|
||||
stream.Position = 0;
|
||||
BinaryReader reader = new(stream);
|
||||
TpkCommonString readCommonString = new();
|
||||
readCommonString.Read(reader);
|
||||
int bytesRead = (int)stream.Position;
|
||||
|
||||
Assert.That(bytesRead, Is.EqualTo(bytesWritten));
|
||||
}
|
||||
|
||||
private static TpkCommonString MakeCommonString()
|
||||
{
|
||||
TpkCommonString commonString = new();
|
||||
commonString.Add(Unity4, 5);
|
||||
commonString.Add(Unity6, 10);
|
||||
commonString.Add(Unity4, new TpkCommonString.Entry[5]);
|
||||
commonString.Add(Unity6, new TpkCommonString.Entry[10]);
|
||||
return commonString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>AssetRipper.Tpk.TypeTrees.Json.Tests</RootNamespace>
|
||||
<AssemblyName>AssetRipper.Tpk.TypeTrees.Json.Tests</AssemblyName>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="NUnit" Version="4.2.2" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.3.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
||||
<PackageReference Include="NUnit" Version="4.6.1" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.14.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -30,8 +30,6 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
result.Module = "";
|
||||
//TypeID gets set elsewhere
|
||||
result.Base = stringBuffer[source.Base];
|
||||
result.Size = -1;
|
||||
//Type index is ignored
|
||||
result.IsAbstract = source.Flags.IsAbstract();
|
||||
result.IsSealed = source.Flags.IsSealed();
|
||||
result.IsEditorOnly = source.Flags.IsEditorOnly();
|
||||
@@ -39,11 +37,11 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
result.IsStripped = source.Flags.IsStripped();
|
||||
if (source.EditorRootNode != ushort.MaxValue)
|
||||
{
|
||||
result.EditorRootNode = NodeConversion.Convert(nodeBuffer[source.EditorRootNode], stringBuffer, nodeBuffer, 0, 0, out var _);
|
||||
result.EditorRootNode = NodeConversion.Convert(nodeBuffer[source.EditorRootNode], stringBuffer, nodeBuffer);
|
||||
}
|
||||
if (source.ReleaseRootNode != ushort.MaxValue)
|
||||
{
|
||||
result.ReleaseRootNode = NodeConversion.Convert(nodeBuffer[source.ReleaseRootNode], stringBuffer, nodeBuffer, 0, 0, out var _);
|
||||
result.ReleaseRootNode = NodeConversion.Convert(nodeBuffer[source.ReleaseRootNode], stringBuffer, nodeBuffer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -24,26 +24,23 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
return nodeBuffer.AddNode(nodeData);
|
||||
}
|
||||
|
||||
public static UnityNode Convert(TpkUnityNode nodeData, TpkStringBuffer stringBuffer, TpkUnityNodeBuffer nodeBuffer, byte level, int index, out int lastIndexUsed)
|
||||
public static UnityNode Convert(TpkUnityNode nodeData, TpkStringBuffer stringBuffer, TpkUnityNodeBuffer nodeBuffer)
|
||||
{
|
||||
UnityNode result = new UnityNode();
|
||||
result.TypeName = stringBuffer[nodeData.TypeName];
|
||||
result.Name = stringBuffer[nodeData.Name];
|
||||
result.Level = level;
|
||||
result.ByteSize = nodeData.ByteSize;
|
||||
result.Index = index;
|
||||
result.Version = nodeData.Version;
|
||||
result.TypeFlags = nodeData.TypeFlags;
|
||||
result.MetaFlag = nodeData.MetaFlag;
|
||||
UnityNode result = new()
|
||||
{
|
||||
TypeName = stringBuffer[nodeData.TypeName],
|
||||
Name = stringBuffer[nodeData.Name],
|
||||
ByteSize = nodeData.ByteSize,
|
||||
Version = nodeData.Version,
|
||||
TypeFlags = nodeData.TypeFlags,
|
||||
MetaFlag = nodeData.MetaFlag,
|
||||
};
|
||||
|
||||
byte levelPlus = unchecked((byte)(level + 1U));
|
||||
lastIndexUsed = index;
|
||||
int subNodeCount = nodeData.SubNodes.Length;
|
||||
result.SubNodes = new List<UnityNode>(subNodeCount);
|
||||
for (int i = 0; i < subNodeCount; i++)
|
||||
{
|
||||
result.SubNodes.Add(Convert(nodeBuffer[nodeData.SubNodes[i]], stringBuffer, nodeBuffer, levelPlus, index + 1, out lastIndexUsed));
|
||||
index = lastIndexUsed;
|
||||
result.SubNodes.Add(Convert(nodeBuffer[nodeData.SubNodes[i]], stringBuffer, nodeBuffer));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,36 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTrimmable>true</IsTrimmable>
|
||||
<RootNamespace>AssetRipper.Tpk.TypeTrees.Json</RootNamespace>
|
||||
<AssemblyName>AssetRipper.Tpk.TypeTrees.Json</AssemblyName>
|
||||
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<Authors>ds5678</Authors>
|
||||
<Company>AssetRipper</Company>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
|
||||
<PackageId>AssetRipper.Tpk.TypeTrees.Json</PackageId>
|
||||
<PackageTags>C#</PackageTags>
|
||||
<RepositoryUrl>https://github.com/AssetRipper/Tpk</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
<Copyright>Copyright (c) 2024 ds5678</Copyright>
|
||||
<Description>Library for type tree serialization.</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AssetRipper.HashAlgorithms" Version="1.0.0" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.301">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
using System.Text.Json;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
public sealed class UnityClass
|
||||
{
|
||||
private string name = "";
|
||||
private string @namespace = "";
|
||||
private string fullName = "";
|
||||
private string module = "";
|
||||
private string @base = "";
|
||||
private List<string> derived = new();
|
||||
|
||||
/// <summary>
|
||||
/// The name of the class not including the namespace
|
||||
/// </summary>
|
||||
public string Name { get => name; set => name = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string Name { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The namespace of the class if it exists
|
||||
/// </summary>
|
||||
public string Namespace { get => @namespace; set => @namespace = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string Namespace { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The full name of the class including the namespace but not an assembly specification
|
||||
/// </summary>
|
||||
public string FullName { get => fullName; set => fullName = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string FullName { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The module containing the class
|
||||
/// </summary>
|
||||
public string Module { get => module; set => module = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string Module { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The unique number used to identify the class
|
||||
/// </summary>
|
||||
@@ -35,26 +33,20 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
/// <summary>
|
||||
/// The name of the base class if it exists. Namespace not included
|
||||
/// </summary>
|
||||
public string Base { get => @base; set => @base = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string Base { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The names of the classes that directly derive from this. Namespaces not included
|
||||
/// </summary>
|
||||
public List<string> Derived { get => derived; set => derived = value ?? new(); }
|
||||
[AllowNull]
|
||||
public List<string> Derived { get; set => field = value ?? []; } = [];
|
||||
/// <summary>
|
||||
/// The count of all classes that descend from this class<br/>
|
||||
/// It includes this class, so the count is always positive<br/>
|
||||
/// However, some older unity versions don't generate this, so sometimes we have to set it in SharedState initialization
|
||||
/// However, some older unity versions don't generate this, so sometimes it needs to be set manually.
|
||||
/// </summary>
|
||||
public uint DescendantCount { get; set; }
|
||||
/// <summary>
|
||||
/// The size in bytes of one object. Doesn't include alignments. May be wildly inaccurate, especially for classes with variable size.
|
||||
/// </summary>
|
||||
public int Size { get; set; }
|
||||
/// <summary>
|
||||
/// The zero based index of this class in the list of acquired classes. Doesn't mean much.
|
||||
/// </summary>
|
||||
public uint TypeIndex { get; set; }
|
||||
/// <summary>
|
||||
/// Is the class abstract?
|
||||
/// </summary>
|
||||
public bool IsAbstract { get; set; }
|
||||
@@ -81,7 +73,9 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
/// <summary>
|
||||
/// The constructor used in json deserialization
|
||||
/// </summary>
|
||||
public UnityClass() { }
|
||||
public UnityClass()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The constructor used to make dependent class definitions
|
||||
@@ -100,7 +94,6 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
TypeID = -1;
|
||||
Derived = new List<string>();
|
||||
DescendantCount = 1;
|
||||
Size = mainRootNode.ByteSize;
|
||||
IsAbstract = false;
|
||||
IsSealed = true;
|
||||
IsEditorOnly = releaseRootNode == null;
|
||||
@@ -153,13 +146,13 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
public string ToJsonString(bool indented = false)
|
||||
{
|
||||
return indented
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContextIndented.Default.UnityClass)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContextNotIndented.Default.UnityClass);
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteIndentedContext.UnityClass)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteNotIndentedContext.UnityClass);
|
||||
}
|
||||
|
||||
public static UnityClass? FromJsonString(string jsonString)
|
||||
{
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContextIndented.Default.UnityClass);
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContext.Default.UnityClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,23 @@
|
||||
using System.Text.Json;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
public sealed class UnityInfo
|
||||
{
|
||||
private string version = "";
|
||||
private List<UnityString> strings = new();
|
||||
private List<UnityClass> classes = new();
|
||||
|
||||
public string Version
|
||||
{
|
||||
get => version;
|
||||
set => version = value ?? "";
|
||||
}
|
||||
|
||||
[AllowNull]
|
||||
public List<UnityString> Strings
|
||||
{
|
||||
get => strings;
|
||||
set => strings = value ?? new();
|
||||
}
|
||||
get;
|
||||
set => field = value ?? new();
|
||||
} = new();
|
||||
|
||||
[AllowNull]
|
||||
public List<UnityClass> Classes
|
||||
{
|
||||
get => classes;
|
||||
set => classes = value ?? new();
|
||||
}
|
||||
get;
|
||||
set => field = value ?? new();
|
||||
} = new();
|
||||
|
||||
public static UnityInfo ReadFromJsonFile(string jsonPath)
|
||||
{
|
||||
@@ -35,18 +28,18 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
public string ToJsonString(bool indented = false)
|
||||
{
|
||||
return indented
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContextIndented.Default.UnityInfo)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContextNotIndented.Default.UnityInfo);
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteIndentedContext.UnityInfo)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteNotIndentedContext.UnityInfo);
|
||||
}
|
||||
|
||||
public static UnityInfo? FromJsonString(string jsonString)
|
||||
{
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContextIndented.Default.UnityInfo);
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContext.Default.UnityInfo);
|
||||
}
|
||||
|
||||
public static UnityInfo? FromStream(Stream utf8JsonStream)
|
||||
{
|
||||
return JsonSerializer.Deserialize(utf8JsonStream, UnityInfoSerializerContextIndented.Default.UnityInfo);
|
||||
return JsonSerializer.Deserialize(utf8JsonStream, UnityInfoSerializerContext.Default.UnityInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
[JsonSourceGenerationOptions(IndentCharacter = '\t', IndentSize = 1)]
|
||||
[JsonSerializable(typeof(UnityInfo))]
|
||||
internal sealed partial class UnityInfoSerializerContext : JsonSerializerContext
|
||||
{
|
||||
public static UnityInfoSerializerContext WriteIndentedContext { get; }
|
||||
public static UnityInfoSerializerContext WriteNotIndentedContext { get; }
|
||||
|
||||
static UnityInfoSerializerContext()
|
||||
{
|
||||
JsonSerializerOptions WriteIndentedOptions = new(s_defaultOptions)
|
||||
{
|
||||
WriteIndented = true,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
};
|
||||
WriteIndentedContext = new UnityInfoSerializerContext(WriteIndentedOptions);
|
||||
|
||||
JsonSerializerOptions WriteNotIndentedOptions = new(s_defaultOptions)
|
||||
{
|
||||
WriteIndented = false,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||
};
|
||||
WriteNotIndentedContext = new UnityInfoSerializerContext(WriteNotIndentedOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(UnityInfo))]
|
||||
internal sealed partial class UnityInfoSerializerContextIndented : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
[JsonSourceGenerationOptions(WriteIndented = false)]
|
||||
[JsonSerializable(typeof(UnityInfo))]
|
||||
internal sealed partial class UnityInfoSerializerContextNotIndented : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using AssetRipper.HashAlgorithms;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
@@ -9,42 +10,39 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
public sealed class UnityNode
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique type name used in the <see cref = "SharedState"/> dictionaries
|
||||
/// </summary>
|
||||
public string TypeName { get => typeName; set => typeName = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string TypeName { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The original type name as obtained from the json file
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[AllowNull]
|
||||
public string OriginalTypeName
|
||||
{
|
||||
get => string.IsNullOrEmpty(originalTypeName) ? TypeName : originalTypeName;
|
||||
set => originalTypeName = value ?? "";
|
||||
}
|
||||
public string Name { get => name; set => name = value ?? ""; }
|
||||
[AllowNull]
|
||||
public string Name { get; set => field = value ?? ""; } = "";
|
||||
/// <summary>
|
||||
/// The original name as obtained from the json file
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[AllowNull]
|
||||
public string OriginalName
|
||||
{
|
||||
get => string.IsNullOrEmpty(originalName) ? Name : originalName;
|
||||
set => originalName = value ?? "";
|
||||
}
|
||||
public byte Level { get; set; }
|
||||
public int ByteSize { get; set; }
|
||||
public int Index { get; set; }
|
||||
public short Version { get; set; }
|
||||
public byte TypeFlags { get; set; }
|
||||
public uint MetaFlag { get; set; }
|
||||
public List<UnityNode> SubNodes { get => subNodes; set => subNodes = value ?? new(); }
|
||||
[AllowNull]
|
||||
public List<UnityNode> SubNodes { get; set => field = value ?? []; } = [];
|
||||
|
||||
private string originalTypeName = "";
|
||||
private string originalName = "";
|
||||
private string typeName = "";
|
||||
private string name = "";
|
||||
private List<UnityNode> subNodes = new();
|
||||
|
||||
/// <summary>
|
||||
/// Deep clones a node and all its subnodes<br/>
|
||||
@@ -53,36 +51,30 @@ namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
/// <returns>The new node</returns>
|
||||
public UnityNode DeepClone()
|
||||
{
|
||||
UnityNode cloned = new UnityNode();
|
||||
cloned.TypeName = CloneString(TypeName);
|
||||
cloned.originalTypeName = CloneString(originalTypeName);
|
||||
cloned.Name = CloneString(Name);
|
||||
cloned.originalName = CloneString(originalName);
|
||||
cloned.Level = Level;
|
||||
cloned.ByteSize = ByteSize;
|
||||
cloned.Index = Index;
|
||||
cloned.Version = Version;
|
||||
cloned.TypeFlags = TypeFlags;
|
||||
cloned.MetaFlag = MetaFlag;
|
||||
cloned.SubNodes = SubNodes.ConvertAll(x => x.DeepClone());
|
||||
return cloned;
|
||||
}
|
||||
|
||||
private static string CloneString(string? @string)
|
||||
{
|
||||
return @string == null ? "" : new string(@string);
|
||||
return new UnityNode
|
||||
{
|
||||
TypeName = TypeName,
|
||||
originalTypeName = originalTypeName,
|
||||
Name = Name,
|
||||
originalName = originalName,
|
||||
ByteSize = ByteSize,
|
||||
Version = Version,
|
||||
TypeFlags = TypeFlags,
|
||||
MetaFlag = MetaFlag,
|
||||
SubNodes = SubNodes.ConvertAll(x => x.DeepClone()),
|
||||
};
|
||||
}
|
||||
|
||||
public string ToJsonString(bool indented = false)
|
||||
{
|
||||
return indented
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContextIndented.Default.UnityNode)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContextNotIndented.Default.UnityNode);
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteIndentedContext.UnityNode)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteNotIndentedContext.UnityNode);
|
||||
}
|
||||
|
||||
public static UnityNode? FromJsonString(string jsonString)
|
||||
{
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContextIndented.Default.UnityNode);
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContext.Default.UnityNode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
using System.Text.Json;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AssetRipper.Tpk.TypeTrees.Json
|
||||
{
|
||||
public sealed class UnityString
|
||||
public sealed record class UnityString
|
||||
{
|
||||
private string @string = "";
|
||||
|
||||
public uint Index { get; set; }
|
||||
public string String { get => @string; set => @string = value ?? ""; }
|
||||
|
||||
[AllowNull]
|
||||
public string String { get; set => field = value ?? ""; } = "";
|
||||
|
||||
public string ToJsonString(bool indented = false)
|
||||
{
|
||||
return indented
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContextIndented.Default.UnityString)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContextNotIndented.Default.UnityString);
|
||||
? JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteIndentedContext.UnityString)
|
||||
: JsonSerializer.Serialize(this, UnityInfoSerializerContext.WriteNotIndentedContext.UnityString);
|
||||
}
|
||||
|
||||
public static UnityString? FromJsonString(string jsonString)
|
||||
{
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContextIndented.Default.UnityString);
|
||||
return JsonSerializer.Deserialize(jsonString, UnityInfoSerializerContext.Default.UnityString);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.32112.339
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B80E65C0-145A-4034-9EC8-E2D03ECAE732}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.editorconfig = .editorconfig
|
||||
.gitignore = .gitignore
|
||||
License.md = License.md
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{33E54A6F-8689-4D4A-AA4F-CB68BDEE8FF4}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\engine_assets_tpk.yml = .github\workflows\engine_assets_tpk.yml
|
||||
.github\workflows\test.yml = .github\workflows\test.yml
|
||||
.github\workflows\type_tree_tpk.yml = .github\workflows\type_tree_tpk.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tpk", "Tpk\Tpk.csproj", "{E209C981-9B4C-4F85-94D1-BE3BE279FFE9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tpk.ConsoleApp", "Tpk.ConsoleApp\Tpk.ConsoleApp.csproj", "{C72B5264-B6E5-4182-A0D1-D0D95D310C26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tpk.Tests", "Tpk.Tests\Tpk.Tests.csproj", "{35439820-AA58-4808-9CB0-C749A72E6E84}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tpk.TypeTrees.Json", "Tpk.TypeTrees.Json\Tpk.TypeTrees.Json.csproj", "{7EE04F87-29D5-40C1-A844-E69E22A0EC2F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tpk.TypeTrees.Json.Tests", "Tpk.TypeTrees.Json.Tests\Tpk.TypeTrees.Json.Tests.csproj", "{4D312207-79EB-4289-A855-9517AD25AD88}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{E209C981-9B4C-4F85-94D1-BE3BE279FFE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E209C981-9B4C-4F85-94D1-BE3BE279FFE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E209C981-9B4C-4F85-94D1-BE3BE279FFE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E209C981-9B4C-4F85-94D1-BE3BE279FFE9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C72B5264-B6E5-4182-A0D1-D0D95D310C26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C72B5264-B6E5-4182-A0D1-D0D95D310C26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C72B5264-B6E5-4182-A0D1-D0D95D310C26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C72B5264-B6E5-4182-A0D1-D0D95D310C26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{35439820-AA58-4808-9CB0-C749A72E6E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35439820-AA58-4808-9CB0-C749A72E6E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35439820-AA58-4808-9CB0-C749A72E6E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{35439820-AA58-4808-9CB0-C749A72E6E84}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7EE04F87-29D5-40C1-A844-E69E22A0EC2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7EE04F87-29D5-40C1-A844-E69E22A0EC2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7EE04F87-29D5-40C1-A844-E69E22A0EC2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7EE04F87-29D5-40C1-A844-E69E22A0EC2F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D312207-79EB-4289-A855-9517AD25AD88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D312207-79EB-4289-A855-9517AD25AD88}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D312207-79EB-4289-A855-9517AD25AD88}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D312207-79EB-4289-A855-9517AD25AD88}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{33E54A6F-8689-4D4A-AA4F-CB68BDEE8FF4} = {B80E65C0-145A-4034-9EC8-E2D03ECAE732}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B4F6071A-E37E-4782-9BDD-92C8A73D4820}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,19 @@
|
||||
<Solution>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path=".editorconfig" />
|
||||
<File Path=".gitignore" />
|
||||
<File Path="Directory.Build.props" />
|
||||
<File Path="License.md" />
|
||||
<File Path="README.md" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Items/workflows/">
|
||||
<File Path=".github/workflows/engine_assets_tpk.yml" />
|
||||
<File Path=".github/workflows/test.yml" />
|
||||
<File Path=".github/workflows/type_tree_tpk.yml" />
|
||||
</Folder>
|
||||
<Project Path="Tpk.ConsoleApp/Tpk.ConsoleApp.csproj" />
|
||||
<Project Path="Tpk.Tests/Tpk.Tests.csproj" />
|
||||
<Project Path="Tpk.TypeTrees.Json.Tests/Tpk.TypeTrees.Json.Tests.csproj" />
|
||||
<Project Path="Tpk.TypeTrees.Json/Tpk.TypeTrees.Json.csproj" />
|
||||
<Project Path="Tpk/Tpk.csproj" />
|
||||
</Solution>
|
||||
@@ -9,7 +9,7 @@ namespace AssetRipper.Tpk.Compression
|
||||
LzmaEncoderProperties properties = new LzmaEncoderProperties(false, 1 << 25, 256);
|
||||
using MemoryStream inputStream = new MemoryStream(uncompressedBytes);
|
||||
using MemoryStream outputStream = new MemoryStream();
|
||||
using LzmaStream lzmaStream = new LzmaStream(properties, false, outputStream);
|
||||
using LzmaStream lzmaStream = LzmaStream.Create(properties, false, outputStream);
|
||||
outputStream.Write(lzmaStream.Properties);
|
||||
inputStream.CopyTo(lzmaStream);
|
||||
lzmaStream.Close();
|
||||
@@ -25,7 +25,7 @@ namespace AssetRipper.Tpk.Compression
|
||||
using MemoryStream inputStream = new MemoryStream(compressedBytes);
|
||||
inputStream.Position = 5;
|
||||
using MemoryStream outputStream = new MemoryStream();
|
||||
using LzmaStream lzmaStream = new LzmaStream(properties, inputStream, compressedBytes.Length - 5, decompressedSize);
|
||||
using LzmaStream lzmaStream = LzmaStream.Create(properties, inputStream, compressedBytes.Length - 5, decompressedSize);
|
||||
lzmaStream.CopyTo(outputStream);
|
||||
return outputStream.ToArray();
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace AssetRipper.Tpk.Compression
|
||||
byte[] properties = new Span<byte>(compressedBytes, 0, 5).ToArray();
|
||||
MemoryStream inputStream = new MemoryStream(compressedBytes);
|
||||
inputStream.Position = 5;
|
||||
return new LzmaStream(properties, inputStream, compressedBytes.Length - 5, decompressedSize);
|
||||
return LzmaStream.Create(properties, inputStream, compressedBytes.Length - 5, decompressedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-19
@@ -1,41 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTrimmable>true</IsTrimmable>
|
||||
<RootNamespace>AssetRipper.Tpk</RootNamespace>
|
||||
<AssemblyName>AssetRipper.Tpk</AssemblyName>
|
||||
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<Authors>ds5678</Authors>
|
||||
<Company>AssetRipper</Company>
|
||||
<Version>1.0.1</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
|
||||
<PackageId>AssetRipper.Tpk</PackageId>
|
||||
<PackageTags>C#</PackageTags>
|
||||
<RepositoryUrl>https://github.com/AssetRipper/Tpk</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
<Copyright>Copyright (c) 2024 ds5678</Copyright>
|
||||
<Description>Library for storing asset information.</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AssetRipper.Primitives" Version="3.1.3" />
|
||||
<PackageReference Include="AssetRipper.Primitives" Version="3.2.0" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.301">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SharpCompress" Version="0.38.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.49.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -8,7 +8,7 @@
|
||||
/// <summary>
|
||||
/// Name : Blob
|
||||
/// </summary>
|
||||
public List<KeyValuePair<string, TpkDataBlob>> Blobs { get; } = new List<KeyValuePair<string, TpkDataBlob>>();
|
||||
public List<KeyValuePair<string, TpkDataBlob>> Blobs { get; } = [];
|
||||
|
||||
public override TpkDataType DataType => TpkDataType.Collection;
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ namespace AssetRipper.Tpk
|
||||
public sealed class TpkFile
|
||||
{
|
||||
public const uint TpkMagicBytes = 0x2A4B5054; // TPK* in binary
|
||||
public const byte TpkVersionNumber = 1;
|
||||
public const byte TpkVersionNumber = 2;
|
||||
|
||||
public TpkCompressionType CompressionType { get; private set; }
|
||||
public TpkDataType DataType { get; private set; }
|
||||
|
||||
@@ -21,7 +21,9 @@ namespace AssetRipper.Tpk.TypeTrees
|
||||
/// </summary>
|
||||
public List<VersionClassPair> Classes { get; } = new();
|
||||
|
||||
public TpkClassInformation() { }
|
||||
public TpkClassInformation()
|
||||
{
|
||||
}
|
||||
|
||||
public TpkClassInformation(int id)
|
||||
{
|
||||
|
||||
@@ -9,33 +9,51 @@ namespace AssetRipper.Tpk.TypeTrees
|
||||
public sealed class TpkCommonString
|
||||
{
|
||||
/// <summary>
|
||||
/// Unity version : string count<br/>
|
||||
/// Sequential by ascending Unity version
|
||||
/// An entry in <see cref="TpkCommonString"/>
|
||||
/// </summary>
|
||||
public List<KeyValuePair<UnityVersion, byte>> VersionInformation { get; } = new();
|
||||
public List<ushort> StringBufferIndices { get; } = new();
|
||||
|
||||
public void Add(UnityVersion version, byte count)
|
||||
/// <param name="Offset">The byte offset of the string</param>
|
||||
/// <param name="String">The index of the string in <see cref="TpkStringBuffer"/></param>
|
||||
public readonly record struct Entry(ushort Offset, ushort String)
|
||||
{
|
||||
VersionInformation.Add(new KeyValuePair<UnityVersion, byte>(version, count));
|
||||
}
|
||||
|
||||
public void SetIndices(TpkStringBuffer buffer, List<string> strings)
|
||||
{
|
||||
int count = strings.Count;
|
||||
StringBufferIndices.Clear();
|
||||
StringBufferIndices.Capacity = count;
|
||||
for (int i = 0; i < count; i++)
|
||||
public Entry(ushort offset, string @string, TpkStringBuffer buffer) : this(offset, buffer.AddString(@string))
|
||||
{
|
||||
StringBufferIndices.Add(buffer.AddString(strings[i]));
|
||||
}
|
||||
|
||||
public string ToString(TpkStringBuffer buffer)
|
||||
{
|
||||
return buffer[String];
|
||||
}
|
||||
|
||||
public static Entry Read(BinaryReader reader)
|
||||
{
|
||||
ushort offset = reader.ReadUInt16();
|
||||
ushort stringIndex = reader.ReadUInt16();
|
||||
return new Entry(offset, stringIndex);
|
||||
}
|
||||
|
||||
public void Write(BinaryWriter writer)
|
||||
{
|
||||
writer.Write(Offset);
|
||||
writer.Write(String);
|
||||
}
|
||||
}
|
||||
|
||||
public byte GetCount(UnityVersion exactVersion)
|
||||
/// <summary>
|
||||
/// Unity version : string count<br/>
|
||||
/// Sequential by ascending Unity version
|
||||
/// </summary>
|
||||
public List<KeyValuePair<UnityVersion, Entry[]>> VersionInformation { get; } = new();
|
||||
|
||||
public void Add(UnityVersion version, Entry[] entries)
|
||||
{
|
||||
VersionInformation.Add(new KeyValuePair<UnityVersion, Entry[]>(version, entries));
|
||||
}
|
||||
|
||||
public Entry[] GetEntries(UnityVersion exactVersion)
|
||||
{
|
||||
if (VersionInformation.Count == 0)
|
||||
{
|
||||
return 0;
|
||||
return [];
|
||||
}
|
||||
for (int i = 1; i < VersionInformation.Count; i++)
|
||||
{
|
||||
@@ -44,18 +62,7 @@ namespace AssetRipper.Tpk.TypeTrees
|
||||
return VersionInformation[i - 1].Value;
|
||||
}
|
||||
}
|
||||
return VersionInformation[VersionInformation.Count - 1].Value;
|
||||
}
|
||||
|
||||
public string[] GetStrings(TpkStringBuffer buffer)
|
||||
{
|
||||
int length = StringBufferIndices.Count;
|
||||
string[] strings = new string[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
strings[i] = buffer[StringBufferIndices[i]];
|
||||
}
|
||||
return strings;
|
||||
return VersionInformation[^1].Value;
|
||||
}
|
||||
|
||||
public void Read(BinaryReader reader)
|
||||
@@ -66,15 +73,13 @@ namespace AssetRipper.Tpk.TypeTrees
|
||||
for (int i = 0; i < versionCount; i++)
|
||||
{
|
||||
UnityVersion version = reader.ReadUnityVersion();
|
||||
byte stringCount = reader.ReadByte();
|
||||
VersionInformation.Add(new KeyValuePair<UnityVersion, byte>(version, stringCount));
|
||||
}
|
||||
int indicesCount = reader.ReadInt32();
|
||||
StringBufferIndices.Clear();
|
||||
StringBufferIndices.Capacity = indicesCount;
|
||||
for (int j = 0; j < indicesCount; j++)
|
||||
{
|
||||
StringBufferIndices.Add(reader.ReadUInt16());
|
||||
int entryCount = reader.ReadInt32();
|
||||
Entry[] entries = new Entry[entryCount];
|
||||
for (int j = 0; j < entryCount; j++)
|
||||
{
|
||||
entries[j] = Entry.Read(reader);
|
||||
}
|
||||
VersionInformation.Add(new KeyValuePair<UnityVersion, Entry[]>(version, entries));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +89,12 @@ namespace AssetRipper.Tpk.TypeTrees
|
||||
for (int i = 0; i < VersionInformation.Count; i++)
|
||||
{
|
||||
writer.Write(VersionInformation[i].Key);
|
||||
writer.Write(VersionInformation[i].Value);
|
||||
}
|
||||
writer.Write(StringBufferIndices.Count);
|
||||
for (int i = 0; i < StringBufferIndices.Count; i++)
|
||||
{
|
||||
writer.Write(StringBufferIndices[i]);
|
||||
Entry[] entries = VersionInformation[i].Value;
|
||||
writer.Write(entries.Length);
|
||||
for (int j = 0; j < entries.Length; j++)
|
||||
{
|
||||
entries[j].Write(writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
|
||||
//Derived and Descendent count are excluded from this format
|
||||
|
||||
//Size and TypeIndex are excluded from this format
|
||||
|
||||
/// <summary>
|
||||
/// 8 boolean values packed into 1 byte
|
||||
/// </summary>
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
{
|
||||
public ushort TypeName { get; set; }
|
||||
public ushort Name { get; set; }
|
||||
//Level is redundant
|
||||
public int ByteSize { get; set; }
|
||||
//Index is redundant
|
||||
public short Version { get; set; }
|
||||
public byte TypeFlags { get; set; }
|
||||
public uint MetaFlag { get; set; }
|
||||
public ushort[] SubNodes { get; set; } = Array.Empty<ushort>();
|
||||
public ushort[] SubNodes { get; set; } = [];
|
||||
|
||||
public void Read(BinaryReader reader)
|
||||
{
|
||||
@@ -62,21 +60,7 @@
|
||||
Version == other.Version &&
|
||||
TypeFlags == other.TypeFlags &&
|
||||
MetaFlag == other.MetaFlag &&
|
||||
ArrayEqual(SubNodes, other.SubNodes);
|
||||
}
|
||||
|
||||
private static bool ArrayEqual(ushort[] array1, ushort[] array2)
|
||||
{
|
||||
if (array1.Length != array2.Length)
|
||||
return false;
|
||||
for (int i = 0; i < array1.Length; i++)
|
||||
{
|
||||
if (array1[i] != array2[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
SubNodes.SequenceEqual(other.SubNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user