mirror of
https://gitea.tendokyu.moe/Kayori/Medusa.net.git
synced 2026-09-27 17:28:01 +03:00
- Refactor handler dispatch to use a parsed GameModel instead of raw model strings (Handler.cs, HandlerService.cs, new GameModel.cs) - Add a Unity asset-extraction subsystem (Abstractions/Extractors/Unity) - Add WriteEventLogHandler, XrpcDouble serialization type - Rename EaCoin*Handler -> *EaCoinHandler for naming consistency - Add PIN/username update and forgot/reset password flows, with a console-logging IEmailSender until real email is wired up - Add a settings page and a theming pass (theme tokens, tailwind config) - Add plugin nav/route/UI-manifest frontend types
91 lines
3.9 KiB
C#
91 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Abstractions.Extractors.Unity.Helpers;
|
|
using Abstractions.Extractors.Unity.Services;
|
|
|
|
namespace Abstractions.Extractors.Unity;
|
|
|
|
/// <summary>Extracts a Material's shader reference, keywords, and saved properties (textures/floats/
|
|
/// colors) to JSON. Falls back to a raw typetree dump if m_SavedProperties doesn't look as expected.</summary>
|
|
public sealed class MaterialExtractor : IAssetExtractor
|
|
{
|
|
public IReadOnlyCollection<string> HandledTypes { get; } = ["Material"];
|
|
|
|
public async Task<bool> ExtractAsync(ExtractionContext context, CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
var baseField = context.BaseField;
|
|
|
|
context.Loader.TryResolvePPtrName(context.FileInstance, baseField.Get("m_Shader"), out var shaderName);
|
|
var shaderPptr = baseField.Get("m_Shader");
|
|
ReflectionHelper.TryGetPPtr(shaderPptr, out var shaderPathId, out _);
|
|
|
|
var materialData = new Dictionary<string, object?>
|
|
{
|
|
["name"] = baseField.Get("m_Name") is { IsDummy: false } n ? n.AsString : "Unknown",
|
|
["shader"] = new Dictionary<string, object?>
|
|
{
|
|
["name"] = string.IsNullOrEmpty(shaderName) ? "Unknown" : shaderName,
|
|
["path_id"] = shaderPathId,
|
|
},
|
|
["keywords"] = ReflectionHelper.ToPlainObject(baseField.Get("m_ShaderKeywords")),
|
|
["properties"] = new Dictionary<string, object?>(),
|
|
["textures"] = new Dictionary<string, object?>(),
|
|
};
|
|
|
|
var textures = (Dictionary<string, object?>)materialData["textures"]!;
|
|
var properties = (Dictionary<string, object?>)materialData["properties"]!;
|
|
|
|
var savedProps = baseField.Get("m_SavedProperties");
|
|
if (!savedProps.IsDummy)
|
|
{
|
|
foreach (var pair in BundleLoader.ArrayElements(savedProps.Get("m_TexEnvs")))
|
|
{
|
|
var texName = pair.Get("first").AsString;
|
|
var texData = pair.Get("second");
|
|
if (texData.IsDummy) continue;
|
|
|
|
ReflectionHelper.TryGetPPtr(texData.Get("m_Texture"), out var texPathId, out _);
|
|
var scale = texData.Get("m_Scale");
|
|
var offset = texData.Get("m_Offset");
|
|
|
|
textures[texName] = new Dictionary<string, object?>
|
|
{
|
|
["texture_path_id"] = texPathId,
|
|
["scale"] = new[] { scale.Get("x").AsFloat, scale.Get("y").AsFloat },
|
|
["offset"] = new[] { offset.Get("x").AsFloat, offset.Get("y").AsFloat },
|
|
};
|
|
}
|
|
|
|
foreach (var pair in BundleLoader.ArrayElements(savedProps.Get("m_Floats")))
|
|
{
|
|
properties[pair.Get("first").AsString] = new Dictionary<string, object?>
|
|
{
|
|
["type"] = "float",
|
|
["value"] = pair.Get("second").AsFloat,
|
|
};
|
|
}
|
|
|
|
foreach (var pair in BundleLoader.ArrayElements(savedProps.Get("m_Colors")))
|
|
{
|
|
var color = pair.Get("second");
|
|
properties[pair.Get("first").AsString] = new Dictionary<string, object?>
|
|
{
|
|
["type"] = "color",
|
|
["value"] = new[] { color.Get("r").AsFloat, color.Get("g").AsFloat, color.Get("b").AsFloat, color.Get("a").AsFloat },
|
|
};
|
|
}
|
|
}
|
|
|
|
await ObjectSerializer.WriteJsonAsync(materialData, context.OutputPathNoExtension + ".json", cancellationToken);
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return await FallbackExtractor.WriteTypeTreeDumpAsync(context, cancellationToken);
|
|
}
|
|
}
|
|
}
|