XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;

namespace XFEEDToolBox.Core.Galaxy;

/// <summary>Complete original Stellar Forge density raster, in the game's Galactic coordinate frame.</summary>
public sealed record GalaxyDensityMap(int Width,int Height,double OriginX,double OriginZ,double ExtentX,double ExtentZ,byte[] Values,bool FloatValues=false)
{
    public static GalaxyDensityMap Read(string path)
    {
        if(new FileInfo(path).Length is <48 or >66*1024*1024)throw new InvalidDataException("银河全景资源大小无效。");
        return Parse(File.ReadAllBytes(path));
    }
    public static GalaxyDensityMap Parse(ReadOnlySpan<byte> data)
    {
        if(data.Length<48||!(data[..8].SequenceEqual("XFEGDM1\0"u8)||data[..8].SequenceEqual("XFEGDM2\0"u8)))throw new InvalidDataException("银河全景资源头无效。");
        var floats=data[6]=='2';var stride=floats?4:2;
        var width=BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8,4));var height=BinaryPrimitives.ReadInt32LittleEndian(data.Slice(12,4));
        var ox=BinaryPrimitives.ReadDoubleLittleEndian(data.Slice(16,8));var oz=BinaryPrimitives.ReadDoubleLittleEndian(data.Slice(24,8));
        var ex=BinaryPrimitives.ReadDoubleLittleEndian(data.Slice(32,8));var ez=BinaryPrimitives.ReadDoubleLittleEndian(data.Slice(40,8));
        if(width is <16 or >8192||height is <16 or >8192||(long)width*height>16777216||data.Length!=48+(long)width*height*stride
            ||!double.IsFinite(ox+oz+ex+ez)||Math.Abs(ox)>1000000||Math.Abs(oz)>1000000||ex is <1000 or >1000000||ez is <1000 or >1000000)
            throw new InvalidDataException("银河全景范围或像素数据不完整。");
        if(floats)for(var i=48;i<data.Length;i+=4)
        {
            var value=BinaryPrimitives.ReadSingleLittleEndian(data.Slice(i,4));
            if(!float.IsFinite(value)||value<0||value>1)throw new InvalidDataException("银河全景像素超出有效密度范围。");
        }
        return new(width,height,ox,oz,ex,ez,data[48..].ToArray(),floats);
    }
}