using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Abstractions.Extractors.Unity.Helpers;
using Abstractions.Extractors.Unity.Services;
using AssetsTools.NET;
namespace Abstractions.Extractors.Unity;
/// Dumps a MonoBehaviour's full typetree, or falls back to a handful of always-present
/// base fields if that can't be serialized.
public sealed class MonoBehaviourExtractor : IAssetExtractor
{
public IReadOnlyCollection HandledTypes { get; } = ["MonoBehaviour"];
public async Task ExtractAsync(ExtractionContext context, CancellationToken cancellationToken = default)
{
var baseField = context.BaseField;
try
{
var info = ObjectSerializer.ReadTypeTree(baseField);
await ObjectSerializer.WriteJsonAsync(info, context.OutputPathNoExtension + ".json", cancellationToken);
return true;
}
catch
{
TryGetPPtrPathId(baseField, "m_GameObject", out var gameObjectPathId);
TryGetPPtrPathId(baseField, "m_Script", out var scriptPathId);
var basicFields = new Dictionary
{
["m_Name"] = baseField.Get("m_Name") is { IsDummy: false } n ? n.AsString : "Unknown",
["m_Enabled"] = baseField.Get("m_Enabled") is { IsDummy: false } e ? e.AsBool : true,
["m_GameObject_PathID"] = gameObjectPathId,
["m_Script_PathID"] = scriptPathId,
};
await ObjectSerializer.WriteJsonAsync(basicFields, context.OutputPathNoExtension + "_basic.json", cancellationToken);
return true;
}
}
private static void TryGetPPtrPathId(AssetTypeValueField baseField, string fieldName, out long pathId)
{
pathId = -1;
var pptr = baseField.Get(fieldName);
if (!pptr.IsDummy && ReflectionHelper.TryGetPPtr(pptr, out var resolved, out _))
pathId = resolved;
}
}