first commit
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
using AddressablesTools.Catalog;
|
||||
using AddressablesTools.JSON;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace AddressablesTools
|
||||
{
|
||||
public static class AddressablesJsonParser
|
||||
{
|
||||
internal static ContentCatalogDataJson CCDJsonFromString(string data)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<ContentCatalogDataJson>(data);
|
||||
}
|
||||
|
||||
public static ContentCatalogData FromString(string data)
|
||||
{
|
||||
ContentCatalogDataJson ccdJson = CCDJsonFromString(data);
|
||||
|
||||
ContentCatalogData catalogData = new ContentCatalogData();
|
||||
catalogData.Read(ccdJson);
|
||||
|
||||
return catalogData;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
internal class ClassJsonObject
|
||||
{
|
||||
public string AssemblyName { get; }
|
||||
public string ClassName { get; }
|
||||
public string JsonText { get; }
|
||||
|
||||
public ClassJsonObject(string assemblyName, string className, string jsonText)
|
||||
{
|
||||
AssemblyName = assemblyName;
|
||||
ClassName = className;
|
||||
JsonText = jsonText;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,177 @@
|
||||
using AddressablesTools.JSON;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
public class ContentCatalogData
|
||||
{
|
||||
public string LocatorId { get; set; }
|
||||
public ObjectInitializationData InstanceProviderData { get; set; }
|
||||
public ObjectInitializationData SceneProviderData { get; set; }
|
||||
public ObjectInitializationData[] ResourceProviderData { get; set; }
|
||||
public string[] ProviderIds { get; set; }
|
||||
public string[] InternalIds { get; set; }
|
||||
public SerializedType[] ResourceTypes { get; set; }
|
||||
public string[] InternalIdPrefixes { get; set; }
|
||||
|
||||
public Dictionary<object, List<ResourceLocation>> Resources { get; set; }
|
||||
|
||||
internal void Read(ContentCatalogDataJson data)
|
||||
{
|
||||
LocatorId = data.m_LocatorId;
|
||||
|
||||
InstanceProviderData = new ObjectInitializationData();
|
||||
InstanceProviderData.Read(data.m_InstanceProviderData);
|
||||
|
||||
SceneProviderData = new ObjectInitializationData();
|
||||
SceneProviderData.Read(data.m_SceneProviderData);
|
||||
|
||||
ResourceProviderData = new ObjectInitializationData[data.m_ResourceProviderData.Length];
|
||||
for (int i = 0; i < ResourceProviderData.Length; i++)
|
||||
{
|
||||
ResourceProviderData[i] = new ObjectInitializationData();
|
||||
ResourceProviderData[i].Read(data.m_ResourceProviderData[i]);
|
||||
}
|
||||
|
||||
ProviderIds = new string[data.m_ProviderIds.Length];
|
||||
for (int i = 0; i < ProviderIds.Length; i++)
|
||||
{
|
||||
ProviderIds[i] = data.m_ProviderIds[i];
|
||||
}
|
||||
|
||||
InternalIds = new string[data.m_InternalIds.Length];
|
||||
for (int i = 0; i < InternalIds.Length; i++)
|
||||
{
|
||||
InternalIds[i] = data.m_InternalIds[i];
|
||||
}
|
||||
|
||||
ResourceTypes = new SerializedType[data.m_resourceTypes.Length];
|
||||
for (int i = 0; i < ResourceTypes.Length; i++)
|
||||
{
|
||||
ResourceTypes[i] = new SerializedType();
|
||||
ResourceTypes[i].Read(data.m_resourceTypes[i]);
|
||||
}
|
||||
|
||||
InternalIdPrefixes = new string[data.m_InternalIdPrefixes.Length];
|
||||
for (int i = 0; i < InternalIdPrefixes.Length; i++)
|
||||
{
|
||||
InternalIdPrefixes[i] = data.m_InternalIdPrefixes[i];
|
||||
}
|
||||
|
||||
ReadResources(data);
|
||||
}
|
||||
|
||||
private void ReadResources(ContentCatalogDataJson data)
|
||||
{
|
||||
List<Bucket> buckets;
|
||||
|
||||
MemoryStream bucketStream = new MemoryStream(Convert.FromBase64String(data.m_BucketDataString));
|
||||
using (BinaryReader bucketReader = new BinaryReader(bucketStream))
|
||||
{
|
||||
int bucketCount = bucketReader.ReadInt32();
|
||||
buckets = new List<Bucket>(bucketCount);
|
||||
|
||||
for (int i = 0; i < bucketCount; i++)
|
||||
{
|
||||
int offset = bucketReader.ReadInt32();
|
||||
|
||||
int entryCount = bucketReader.ReadInt32();
|
||||
int[] entries = new int[entryCount];
|
||||
for (int j = 0; j < entryCount; j++)
|
||||
{
|
||||
entries[j] = bucketReader.ReadInt32();
|
||||
}
|
||||
|
||||
buckets.Add(new Bucket(offset, entries));
|
||||
}
|
||||
}
|
||||
|
||||
List<object> keys;
|
||||
|
||||
MemoryStream keyDataStream = new MemoryStream(Convert.FromBase64String(data.m_KeyDataString));
|
||||
using (BinaryReader keyReader = new BinaryReader(keyDataStream))
|
||||
{
|
||||
int keyCount = keyReader.ReadInt32();
|
||||
keys = new List<object>(keyCount);
|
||||
|
||||
for (int i = 0; i < keyCount; i++)
|
||||
{
|
||||
keyDataStream.Position = buckets[i].offset;
|
||||
keys.Add(SerializedObjectDecoder.Decode(keyReader));
|
||||
}
|
||||
}
|
||||
|
||||
List<ResourceLocation> locations;
|
||||
|
||||
MemoryStream entryDataStream = new MemoryStream(Convert.FromBase64String(data.m_EntryDataString));
|
||||
MemoryStream extraDataStream = new MemoryStream(Convert.FromBase64String(data.m_ExtraDataString));
|
||||
using (BinaryReader entryReader = new BinaryReader(entryDataStream))
|
||||
using (BinaryReader extraReader = new BinaryReader(extraDataStream))
|
||||
{
|
||||
int entryCount = entryReader.ReadInt32();
|
||||
locations = new List<ResourceLocation>(entryCount);
|
||||
|
||||
for (int i = 0; i < entryCount; i++)
|
||||
{
|
||||
int internalIdIndex = entryReader.ReadInt32();
|
||||
int providerIndex = entryReader.ReadInt32();
|
||||
int dependencyKeyIndex = entryReader.ReadInt32();
|
||||
int depHash = entryReader.ReadInt32();
|
||||
int dataIndex = entryReader.ReadInt32();
|
||||
int primaryKeyIndex = entryReader.ReadInt32();
|
||||
int resourceTypeIndex = entryReader.ReadInt32();
|
||||
|
||||
string internalId = InternalIds[internalIdIndex];
|
||||
|
||||
string providerId = ProviderIds[providerIndex];
|
||||
|
||||
object dependencyKey = null;
|
||||
if (dependencyKeyIndex >= 0)
|
||||
{
|
||||
dependencyKey = keys[dependencyKeyIndex];
|
||||
}
|
||||
|
||||
object objData = null;
|
||||
if (dataIndex >= 0)
|
||||
{
|
||||
extraDataStream.Position = dataIndex;
|
||||
objData = SerializedObjectDecoder.Decode(extraReader);
|
||||
}
|
||||
|
||||
object primaryKey = keys[primaryKeyIndex];
|
||||
SerializedType resourceType = ResourceTypes[resourceTypeIndex];
|
||||
|
||||
var loc = new ResourceLocation();
|
||||
loc.ReadCompact(internalId, providerId, dependencyKey, objData, depHash, primaryKey, resourceType);
|
||||
locations.Add(loc);
|
||||
}
|
||||
}
|
||||
|
||||
Resources = new Dictionary<object, List<ResourceLocation>>(buckets.Count);
|
||||
for (int i = 0; i < buckets.Count; i++)
|
||||
{
|
||||
int[] bucketEntries = buckets[i].entries;
|
||||
List<ResourceLocation> locs = new List<ResourceLocation>(bucketEntries.Length);
|
||||
for (int j = 0; j < bucketEntries.Length; j++)
|
||||
{
|
||||
locs.Add(locations[bucketEntries[j]]);
|
||||
}
|
||||
Resources[keys[i]] = locs;
|
||||
}
|
||||
}
|
||||
|
||||
private struct Bucket
|
||||
{
|
||||
public int offset;
|
||||
public int[] entries;
|
||||
|
||||
public Bucket(int offset, int[] entries)
|
||||
{
|
||||
this.offset = offset;
|
||||
this.entries = entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
using AddressablesTools.JSON;
|
||||
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
public class ObjectInitializationData
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public SerializedType ObjectType { get; set; }
|
||||
public string Data { get; set; }
|
||||
|
||||
internal void Read(ObjectInitializationDataJson obj)
|
||||
{
|
||||
Id = obj.m_Id;
|
||||
ObjectType = new SerializedType();
|
||||
ObjectType.Read(obj.m_ObjectType);
|
||||
Data = obj.m_Data;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
public class ResourceLocation
|
||||
{
|
||||
public string InternalId { get; set; }
|
||||
public string ProviderId { get; set; }
|
||||
public object Dependency { get; set; }
|
||||
public object Data { get; set; }
|
||||
public int HashCode { get; set; }
|
||||
public int DependencyHashCode { get; set; }
|
||||
public string PrimaryKey { get; set; }
|
||||
public SerializedType Type { get; set; }
|
||||
|
||||
internal void ReadCompact(
|
||||
string internalId, string providerId, object dependencyKey, object data,
|
||||
int depHashCode, object primaryKey, SerializedType resourceType
|
||||
)
|
||||
{
|
||||
InternalId = internalId;
|
||||
ProviderId = providerId;
|
||||
Dependency = dependencyKey;
|
||||
Data = data;
|
||||
HashCode = internalId.GetHashCode() * 31 + providerId.GetHashCode();
|
||||
DependencyHashCode = depHashCode;
|
||||
PrimaryKey = primaryKey.ToString();
|
||||
Type = resourceType;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
internal static class SerializedObjectDecoder
|
||||
{
|
||||
internal enum ObjectType
|
||||
{
|
||||
AsciiString,
|
||||
UnicodeString,
|
||||
UInt16,
|
||||
UInt32,
|
||||
Int32,
|
||||
Hash128,
|
||||
Type,
|
||||
JsonObject
|
||||
}
|
||||
|
||||
internal static object Decode(BinaryReader br)
|
||||
{
|
||||
ObjectType type = (ObjectType)br.ReadByte();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ObjectType.AsciiString:
|
||||
{
|
||||
string str = ReadString4(br);
|
||||
return str;
|
||||
}
|
||||
|
||||
case ObjectType.UnicodeString:
|
||||
{
|
||||
string str = ReadString4Unicode(br);
|
||||
return str;
|
||||
}
|
||||
|
||||
case ObjectType.UInt16:
|
||||
{
|
||||
return br.ReadUInt16();
|
||||
}
|
||||
|
||||
case ObjectType.UInt32:
|
||||
{
|
||||
return br.ReadUInt32();
|
||||
}
|
||||
|
||||
case ObjectType.Int32:
|
||||
{
|
||||
return br.ReadInt32();
|
||||
}
|
||||
|
||||
case ObjectType.Hash128:
|
||||
{
|
||||
// read as string for now
|
||||
string str = ReadString1(br);
|
||||
return str;
|
||||
}
|
||||
|
||||
case ObjectType.Type:
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
throw new NotSupportedException($"{nameof(ObjectType)}.{nameof(ObjectType.Type)} is only supported on windows because it uses {nameof(Type.GetTypeFromCLSID)}");
|
||||
}
|
||||
string str = ReadString1(br);
|
||||
return Type.GetTypeFromCLSID(new Guid(str));
|
||||
}
|
||||
|
||||
case ObjectType.JsonObject:
|
||||
{
|
||||
string assemblyName = ReadString1(br);
|
||||
string className = ReadString1(br);
|
||||
string jsonText = ReadString4Unicode(br);
|
||||
ClassJsonObject jsonObj = new ClassJsonObject(assemblyName, className, jsonText);
|
||||
return jsonObj;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ReadString1(BinaryReader br)
|
||||
{
|
||||
int length = br.ReadByte();
|
||||
string str = Encoding.ASCII.GetString(br.ReadBytes(length));
|
||||
return str;
|
||||
}
|
||||
|
||||
private static string ReadString4(BinaryReader br)
|
||||
{
|
||||
int length = br.ReadInt32();
|
||||
string str = Encoding.ASCII.GetString(br.ReadBytes(length));
|
||||
return str;
|
||||
}
|
||||
|
||||
private static string ReadString4Unicode(BinaryReader br)
|
||||
{
|
||||
int length = br.ReadInt32();
|
||||
string str = Encoding.Unicode.GetString(br.ReadBytes(length));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
using AddressablesTools.JSON;
|
||||
|
||||
namespace AddressablesTools.Catalog
|
||||
{
|
||||
public class SerializedType
|
||||
{
|
||||
public string AssemblyName { get; set; }
|
||||
public string ClassName { get; set; }
|
||||
|
||||
internal void Read(SerializedTypeJson type)
|
||||
{
|
||||
AssemblyName = type.m_AssemblyName;
|
||||
ClassName = type.m_ClassName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
namespace AddressablesTools.JSON
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
internal class ContentCatalogDataJson
|
||||
{
|
||||
public string m_LocatorId { get; set; }
|
||||
public ObjectInitializationDataJson m_InstanceProviderData { get; set; }
|
||||
public ObjectInitializationDataJson m_SceneProviderData { get; set; }
|
||||
public ObjectInitializationDataJson[] m_ResourceProviderData { get; set; }
|
||||
public string[] m_ProviderIds { get; set; }
|
||||
public string[] m_InternalIds { get; set; }
|
||||
public string m_KeyDataString { get; set; }
|
||||
public string m_BucketDataString { get; set; }
|
||||
public string m_EntryDataString { get; set; }
|
||||
public string m_ExtraDataString { get; set; }
|
||||
public SerializedTypeJson[] m_resourceTypes { get; set; }
|
||||
public string[] m_InternalIdPrefixes { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
namespace AddressablesTools.JSON
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
internal class ObjectInitializationDataJson
|
||||
{
|
||||
public string m_Id { get; set; }
|
||||
public SerializedTypeJson m_ObjectType { get; set; }
|
||||
public string m_Data { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
namespace AddressablesTools.JSON
|
||||
{
|
||||
#pragma warning disable IDE1006
|
||||
internal class SerializedTypeJson
|
||||
{
|
||||
public string m_AssemblyName { get; set; }
|
||||
public string m_ClassName { get; set; }
|
||||
}
|
||||
#pragma warning restore IDE1006
|
||||
}
|
Reference in New Issue
Block a user