mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-13 12:14:18 +01:00
Add support for .dat files.
This commit is contained in:
parent
edb05946dd
commit
6a94626a13
10 changed files with 416 additions and 14 deletions
|
|
@ -141,6 +141,7 @@ public partial class CustomizationOptions
|
|||
// Create the initial set with all the easily accessible parameters available for anyone.
|
||||
var set = new CustomizationSet(race, gender)
|
||||
{
|
||||
Voices = row.Voices,
|
||||
HairStyles = GetHairStyles(race, gender),
|
||||
HairColors = hair,
|
||||
SkinColors = skin,
|
||||
|
|
|
|||
148
Glamourer.GameData/Customization/DatCharacterFile.cs
Normal file
148
Glamourer.GameData/Customization/DatCharacterFile.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Dalamud.Memory;
|
||||
|
||||
namespace Glamourer.Customization;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = Size)]
|
||||
public unsafe struct DatCharacterFile
|
||||
{
|
||||
public const int Size = 4 + 4 + 4 + 4 + Penumbra.GameData.Structs.CustomizeData.Size + 2 + 4 + 41 * 4; // 212
|
||||
|
||||
[FieldOffset(0)]
|
||||
private fixed byte _data[Size];
|
||||
|
||||
[FieldOffset(0)]
|
||||
public readonly uint Magic = 0x2013FF14;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public readonly uint Version = 0x05;
|
||||
|
||||
[FieldOffset(8)]
|
||||
private uint _checksum;
|
||||
|
||||
[FieldOffset(12)]
|
||||
private readonly uint _padding = 0;
|
||||
|
||||
[FieldOffset(16)]
|
||||
private Penumbra.GameData.Structs.CustomizeData _customize;
|
||||
|
||||
[FieldOffset(16 + Penumbra.GameData.Structs.CustomizeData.Size)]
|
||||
private ushort _voice;
|
||||
|
||||
[FieldOffset(16 + Penumbra.GameData.Structs.CustomizeData.Size + 2)]
|
||||
private uint _timeStamp;
|
||||
|
||||
[FieldOffset(Size - 41 * 4)]
|
||||
private fixed byte _description[41 * 4];
|
||||
|
||||
public readonly void Write(Stream stream)
|
||||
{
|
||||
for (var i = 0; i < Size; ++i)
|
||||
stream.WriteByte(_data[i]);
|
||||
}
|
||||
|
||||
public static bool Read(Stream stream, out DatCharacterFile file)
|
||||
{
|
||||
if (stream.Length - stream.Position != Size)
|
||||
{
|
||||
file = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
file = new DatCharacterFile(stream);
|
||||
return true;
|
||||
}
|
||||
|
||||
private DatCharacterFile(Stream stream)
|
||||
{
|
||||
for (var i = 0; i < Size; ++i)
|
||||
_data[i] = (byte)stream.ReadByte();
|
||||
}
|
||||
|
||||
public DatCharacterFile(in Customize customize, byte voice, string text)
|
||||
{
|
||||
SetCustomize(customize);
|
||||
SetVoice(voice);
|
||||
SetTime(DateTimeOffset.UtcNow);
|
||||
SetDescription(text);
|
||||
_checksum = CalculateChecksum();
|
||||
}
|
||||
|
||||
public readonly uint CalculateChecksum()
|
||||
{
|
||||
var ret = 0u;
|
||||
for (var i = 16; i < Size; i++)
|
||||
ret ^= (uint)(_data[i] << ((i - 16) % 24));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public readonly uint Checksum
|
||||
=> _checksum;
|
||||
|
||||
public Customize Customize
|
||||
{
|
||||
readonly get => new(_customize);
|
||||
set
|
||||
{
|
||||
SetCustomize(value);
|
||||
_checksum = CalculateChecksum();
|
||||
}
|
||||
}
|
||||
|
||||
public ushort Voice
|
||||
{
|
||||
readonly get => _voice;
|
||||
set
|
||||
{
|
||||
SetVoice(value);
|
||||
_checksum = CalculateChecksum();
|
||||
}
|
||||
}
|
||||
|
||||
public string Description
|
||||
{
|
||||
readonly get
|
||||
{
|
||||
fixed (byte* ptr = _description)
|
||||
{
|
||||
return MemoryHelper.ReadStringNullTerminated((nint)ptr);
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
SetDescription(value);
|
||||
_checksum = CalculateChecksum();
|
||||
}
|
||||
}
|
||||
|
||||
public DateTimeOffset Time
|
||||
{
|
||||
readonly get => DateTimeOffset.FromUnixTimeSeconds(_timeStamp);
|
||||
set
|
||||
{
|
||||
SetTime(value);
|
||||
_checksum = CalculateChecksum();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetTime(DateTimeOffset time)
|
||||
=> _timeStamp = (uint)time.ToUnixTimeSeconds();
|
||||
|
||||
private void SetCustomize(in Customize customize)
|
||||
=> _customize = customize.Data.Clone();
|
||||
|
||||
private void SetVoice(ushort voice)
|
||||
=> _voice = voice;
|
||||
|
||||
private void SetDescription(string text)
|
||||
{
|
||||
fixed (byte* ptr = _description)
|
||||
{
|
||||
var span = new Span<byte>(ptr, 41 * 4);
|
||||
Encoding.UTF8.GetBytes(text.AsSpan(0, Math.Min(40, text.Length)), span);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue