mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-29 11:59:26 +01:00
Glamourer-related changes.
This commit is contained in:
parent
a7ace8a8c8
commit
9e0c38169f
15 changed files with 184 additions and 90 deletions
|
|
@ -1,76 +1,94 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Penumbra.String.Functions;
|
||||
|
||||
namespace Penumbra.GameData.Structs;
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Size = Size)]
|
||||
public unsafe struct CustomizeData : IEquatable< CustomizeData >
|
||||
public unsafe struct CustomizeData : IEquatable<CustomizeData>, IReadOnlyCollection<byte>
|
||||
{
|
||||
public const int Size = 26;
|
||||
|
||||
public fixed byte Data[Size];
|
||||
|
||||
public void Read( void* source )
|
||||
public int Count
|
||||
=> Size;
|
||||
|
||||
public IEnumerator<byte> GetEnumerator()
|
||||
{
|
||||
fixed( byte* ptr = Data )
|
||||
for (var i = 0; i < Size; ++i)
|
||||
yield return At(i);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> GetEnumerator();
|
||||
|
||||
|
||||
private unsafe byte At(int index)
|
||||
=> Data[index];
|
||||
|
||||
public void Read(void* source)
|
||||
{
|
||||
fixed (byte* ptr = Data)
|
||||
{
|
||||
MemoryUtility.MemCpyUnchecked( ptr, source, Size );
|
||||
MemoryUtility.MemCpyUnchecked(ptr, source, Size);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly void Write( void* target )
|
||||
public readonly void Write(void* target)
|
||||
{
|
||||
fixed( byte* ptr = Data )
|
||||
fixed (byte* ptr = Data)
|
||||
{
|
||||
MemoryUtility.MemCpyUnchecked( target, ptr, Size );
|
||||
MemoryUtility.MemCpyUnchecked(target, ptr, Size);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly CustomizeData Clone()
|
||||
{
|
||||
var ret = new CustomizeData();
|
||||
Write( ret.Data );
|
||||
Write(ret.Data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public readonly bool Equals( CustomizeData other )
|
||||
public readonly bool Equals(CustomizeData other)
|
||||
{
|
||||
fixed( byte* ptr = Data )
|
||||
fixed (byte* ptr = Data)
|
||||
{
|
||||
return MemoryUtility.MemCmpUnchecked( ptr, other.Data, Size ) == 0;
|
||||
return MemoryUtility.MemCmpUnchecked(ptr, other.Data, Size) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals( object? obj )
|
||||
=> obj is CustomizeData other && Equals( other );
|
||||
public override bool Equals(object? obj)
|
||||
=> obj is CustomizeData other && Equals(other);
|
||||
|
||||
public static bool Equals(CustomizeData* lhs, CustomizeData* rhs)
|
||||
=> MemoryUtility.MemCmpUnchecked(lhs, rhs, Size) == 0;
|
||||
|
||||
=> MemoryUtility.MemCmpUnchecked(lhs, rhs, Size) == 0;
|
||||
|
||||
/// <remarks>Compare Gender and then only from Height onwards, because all screen actors are set to Height 50,
|
||||
/// the Race is implicitly included in the subrace (after height),
|
||||
/// and the body type is irrelevant for players.</remarks>>
|
||||
/// and the body type is irrelevant for players.</remarks>>
|
||||
public static bool ScreenActorEquals(CustomizeData* lhs, CustomizeData* rhs)
|
||||
=> lhs->Data[1] == rhs->Data[1] && MemoryUtility.MemCmpUnchecked(lhs->Data + 4, rhs->Data + 4, Size - 4) == 0;
|
||||
=> lhs->Data[1] == rhs->Data[1] && MemoryUtility.MemCmpUnchecked(lhs->Data + 4, rhs->Data + 4, Size - 4) == 0;
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
fixed( byte* ptr = Data )
|
||||
fixed (byte* ptr = Data)
|
||||
{
|
||||
var p = ( int* )ptr;
|
||||
var u = *( ushort* )( p + 6 );
|
||||
return HashCode.Combine( *p, p[ 1 ], p[ 2 ], p[ 3 ], p[ 4 ], p[ 5 ], u );
|
||||
var p = (int*)ptr;
|
||||
var u = *(ushort*)(p + 6);
|
||||
return HashCode.Combine(*p, p[1], p[2], p[3], p[4], p[5], u);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly string WriteBase64()
|
||||
{
|
||||
fixed( byte* ptr = Data )
|
||||
fixed (byte* ptr = Data)
|
||||
{
|
||||
var data = new ReadOnlySpan< byte >( ptr, Size );
|
||||
return Convert.ToBase64String( data );
|
||||
var data = new ReadOnlySpan<byte>(ptr, Size);
|
||||
return Convert.ToBase64String(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -78,23 +96,20 @@ public unsafe struct CustomizeData : IEquatable< CustomizeData >
|
|||
{
|
||||
var sb = new StringBuilder(Size * 3);
|
||||
for (var i = 0; i < Size - 1; ++i)
|
||||
{
|
||||
sb.Append($"{Data[i]:X2} ");
|
||||
}
|
||||
sb.Append($"{Data[Size - 1]:X2}");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public bool LoadBase64( string base64 )
|
||||
|
||||
public bool LoadBase64(string base64)
|
||||
{
|
||||
var buffer = stackalloc byte[Size];
|
||||
var span = new Span< byte >( buffer, Size );
|
||||
if( !Convert.TryFromBase64String( base64, span, out var written ) || written != Size )
|
||||
{
|
||||
var span = new Span<byte>(buffer, Size);
|
||||
if (!Convert.TryFromBase64String(base64, span, out var written) || written != Size)
|
||||
return false;
|
||||
}
|
||||
|
||||
Read( buffer );
|
||||
Read(buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
using Dalamud.Utility;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Penumbra.GameData.Enums;
|
||||
using PseudoEquipItem = System.ValueTuple<string, uint, ushort, ushort, ushort, byte, byte>;
|
||||
using PseudoEquipItem = System.ValueTuple<string, ulong, ushort, ushort, ushort, byte, byte>;
|
||||
|
||||
namespace Penumbra.GameData.Structs;
|
||||
|
||||
|
|
@ -10,13 +10,16 @@ namespace Penumbra.GameData.Structs;
|
|||
public readonly struct EquipItem
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly uint Id;
|
||||
public readonly ulong Id;
|
||||
public readonly ushort IconId;
|
||||
public readonly SetId ModelId;
|
||||
public readonly WeaponType WeaponType;
|
||||
public readonly byte Variant;
|
||||
public readonly FullEquipType Type;
|
||||
|
||||
public uint ItemId
|
||||
=> (uint)Id;
|
||||
|
||||
public bool Valid
|
||||
=> Type != FullEquipType.Unknown;
|
||||
|
||||
|
|
@ -35,7 +38,7 @@ public readonly struct EquipItem
|
|||
public EquipItem()
|
||||
=> Name = string.Empty;
|
||||
|
||||
public EquipItem(string name, uint id, ushort iconId, SetId modelId, WeaponType weaponType, byte variant, FullEquipType type)
|
||||
public EquipItem(string name, ulong id, ushort iconId, SetId modelId, WeaponType weaponType, byte variant, FullEquipType type)
|
||||
{
|
||||
Name = string.Intern(name);
|
||||
Id = id;
|
||||
|
|
@ -53,7 +56,7 @@ public readonly struct EquipItem
|
|||
=> new(it.Item1, it.Item2, it.Item3, it.Item4, it.Item5, it.Item6, (FullEquipType)it.Item7);
|
||||
|
||||
public static explicit operator PseudoEquipItem(EquipItem it)
|
||||
=> (it.Name, it.Id, it.IconId, (ushort)it.ModelId, (ushort)it.WeaponType, it.Variant, (byte)it.Type);
|
||||
=> (it.Name, it.ItemId, it.IconId, (ushort)it.ModelId, (ushort)it.WeaponType, it.Variant, (byte)it.Type);
|
||||
|
||||
public static EquipItem FromArmor(Item item)
|
||||
{
|
||||
|
|
@ -90,4 +93,28 @@ public readonly struct EquipItem
|
|||
var variant = (byte)(item.ModelSub >> 32);
|
||||
return new EquipItem(name, id, icon, model, weapon, variant, type);
|
||||
}
|
||||
|
||||
public static EquipItem FromIds(uint itemId, ushort iconId, SetId modelId, WeaponType type, byte variant,
|
||||
FullEquipType equipType = FullEquipType.Unknown, string? name = null)
|
||||
{
|
||||
name ??= $"Unknown ({modelId.Value}-{(type.Value != 0 ? $"{type.Value}-" : string.Empty)}{variant})";
|
||||
var fullId = itemId == 0
|
||||
? modelId.Value | ((ulong)type.Value << 16) | ((ulong)variant << 32) | ((ulong)equipType << 40) | (1ul << 48)
|
||||
: itemId;
|
||||
return new EquipItem(name, fullId, iconId, modelId, type, variant, equipType);
|
||||
}
|
||||
|
||||
|
||||
public static EquipItem FromId(ulong id)
|
||||
{
|
||||
var setId = (SetId)id;
|
||||
var type = (WeaponType)(id >> 16);
|
||||
var variant = (byte)(id >> 32);
|
||||
var equipType = (FullEquipType)(id >> 40);
|
||||
return new EquipItem($"Unknown ({setId.Value}-{(type.Value != 0 ? $"{type.Value}-" : string.Empty)}{variant})", id, 0, setId, type,
|
||||
variant, equipType);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> Name;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue