XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
UTF-8
using Sandbox.Definitions;
using System.Text.RegularExpressions;
using VRage.Game;

namespace SpaceEngineersBlueprintEditor.SpaceEngineersCore.BlueprintEditing;

public enum BlueprintArmorType
{
    Light,
    Heavy
}

public sealed class BlueprintTransformResult
{
    public int ConvertedBlocks { get; internal set; }

    public int AlreadyTargetBlocks { get; internal set; }

    public int UnsupportedBlocks { get; internal set; }

    public int ChangedGrids { get; internal set; }
}

/// <summary>
/// Converts blueprint blocks by using the definitions loaded from the installed game.
/// This keeps the conversion table in sync with game and DLC updates.
/// </summary>
public static class BlueprintTransformService
{
    private static readonly Regex ArmorWeightRegex = new(
        "(?:Light|Heavy)",
        RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);

    public static BlueprintTransformResult ConvertGridSize(
        MyObjectBuilder_ShipBlueprintDefinition blueprint,
        MyCubeSize targetSize)
    {
        if (blueprint is null)
        {
            throw new ArgumentNullException(nameof(blueprint));
        }

        var result = new BlueprintTransformResult();
        foreach (var grid in blueprint.CubeGrids ?? [])
        {
            if (grid.GridSizeEnum != targetSize)
            {
                grid.GridSizeEnum = targetSize;
                result.ChangedGrids++;
            }

            foreach (var block in grid.CubeBlocks ?? [])
            {
                var sourceDefinition = TryGetDefinition(block);
                if (sourceDefinition is null)
                {
                    result.UnsupportedBlocks++;
                    continue;
                }

                if (sourceDefinition.CubeSize == targetSize)
                {
                    result.AlreadyTargetBlocks++;
                    continue;
                }

                var group = MyDefinitionManager.Static.TryGetDefinitionGroup(sourceDefinition.BlockPairName);
                var targetDefinition = targetSize == MyCubeSize.Small ? group?.Small : group?.Large;
                if (targetDefinition is null || targetDefinition.Id.TypeId != block.TypeId)
                {
                    result.UnsupportedBlocks++;
                    continue;
                }

                block.SubtypeName = targetDefinition.Id.SubtypeName;
                result.ConvertedBlocks++;
            }
        }

        return result;
    }

    public static BlueprintTransformResult ConvertArmor(
        MyObjectBuilder_ShipBlueprintDefinition blueprint,
        BlueprintArmorType targetArmor)
    {
        if (blueprint is null)
        {
            throw new ArgumentNullException(nameof(blueprint));
        }

        var targetIsHeavy = targetArmor == BlueprintArmorType.Heavy;
        var candidates = MyDefinitionManager.Static.GetAllDefinitions()
            .OfType<MyCubeBlockDefinition>()
            .Where(IsArmorDefinition)
            .GroupBy(definition => CreateArmorKey(
                definition.BlockPairName,
                definition.CubeSize,
                IsHeavyArmor(definition)))
            .ToDictionary(group => group.Key, group => group.First());

        var result = new BlueprintTransformResult();
        foreach (var grid in blueprint.CubeGrids ?? [])
        {
            foreach (var block in grid.CubeBlocks ?? [])
            {
                var sourceDefinition = TryGetDefinition(block);
                if (sourceDefinition is null || !IsArmorDefinition(sourceDefinition))
                {
                    continue;
                }

                if (IsHeavyArmor(sourceDefinition) == targetIsHeavy)
                {
                    result.AlreadyTargetBlocks++;
                    continue;
                }

                var key = CreateArmorKey(
                    sourceDefinition.BlockPairName,
                    sourceDefinition.CubeSize,
                    targetIsHeavy);
                if (!candidates.TryGetValue(key, out var targetDefinition) ||
                    targetDefinition.Id.TypeId != block.TypeId)
                {
                    result.UnsupportedBlocks++;
                    continue;
                }

                block.SubtypeName = targetDefinition.Id.SubtypeName;
                result.ConvertedBlocks++;
            }
        }

        return result;
    }

    private static MyCubeBlockDefinition? TryGetDefinition(MyObjectBuilder_CubeBlock block)
    {
        try
        {
            return MyDefinitionManager.Static.GetCubeBlockDefinition(block);
        }
        catch
        {
            return null;
        }
    }

    private static bool IsArmorDefinition(MyCubeBlockDefinition definition)
    {
        return definition.BlockPairName.IndexOf("Armor", StringComparison.OrdinalIgnoreCase) >= 0 ||
               definition.Id.SubtypeName.IndexOf("Armor", StringComparison.OrdinalIgnoreCase) >= 0;
    }

    private static bool IsHeavyArmor(MyCubeBlockDefinition definition)
    {
        return definition.BlockPairName.IndexOf("Heavy", StringComparison.OrdinalIgnoreCase) >= 0 ||
               definition.Id.SubtypeName.IndexOf("Heavy", StringComparison.OrdinalIgnoreCase) >= 0;
    }

    private static string NormalizeArmorName(string name)
    {
        return ArmorWeightRegex.Replace(name ?? string.Empty, string.Empty);
    }

    private static string CreateArmorKey(string pairName, MyCubeSize cubeSize, bool isHeavy)
    {
        return $"{NormalizeArmorName(pairName)}|{(int)cubeSize}|{isHeavy}";
    }
}