Net 8, updated submodules

This commit is contained in:
RisaDev
2024-03-21 23:05:36 +03:00
parent 7f18030018
commit d919024f29
18 changed files with 62 additions and 389 deletions

View File

@@ -1,116 +0,0 @@
using Penumbra.GameData.Actors;
using System;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using Penumbra.String;
namespace CustomizePlus.GameData.Data;
public readonly unsafe struct Actor : IEquatable<Actor>
{
private Actor(nint address)
=> Address = address;
public static readonly Actor Null = new(nint.Zero);
public readonly nint Address;
public GameObject* AsObject
=> (GameObject*)Address;
public Character* AsCharacter
=> (Character*)Address;
public bool Valid
=> Address != nint.Zero;
public bool IsCharacter
=> Valid && AsObject->IsCharacter();
public static implicit operator Actor(nint? pointer)
=> new(pointer ?? nint.Zero);
public static implicit operator Actor(GameObject* pointer)
=> new((nint)pointer);
public static implicit operator Actor(Character* pointer)
=> new((nint)pointer);
public static implicit operator nint(Actor actor)
=> actor.Address;
public bool IsGPoseOrCutscene
=> Index.Index is >= (int)ScreenActor.CutsceneStart and < (int)ScreenActor.CutsceneEnd;
public ActorIdentifier GetIdentifier(ActorManager actors)
=> actors.FromObject(AsObject, out _, true, true, false);
public ByteString Utf8Name
=> Valid ? new ByteString(AsObject->Name) : ByteString.Empty;
public bool Identifier(ActorManager actors, out ActorIdentifier ident)
{
if (Valid)
{
ident = GetIdentifier(actors);
return ident.IsValid;
}
ident = ActorIdentifier.Invalid;
return false;
}
public ObjectIndex Index
=> Valid ? AsObject->ObjectIndex : ObjectIndex.AnyIndex;
public Model Model
=> Valid ? AsObject->DrawObject : null;
public byte Job
=> IsCharacter ? AsCharacter->CharacterData.ClassJob : (byte)0;
public static implicit operator bool(Actor actor)
=> actor.Address != nint.Zero;
public static bool operator true(Actor actor)
=> actor.Address != nint.Zero;
public static bool operator false(Actor actor)
=> actor.Address == nint.Zero;
public static bool operator !(Actor actor)
=> actor.Address == nint.Zero;
public bool Equals(Actor other)
=> Address == other.Address;
public override bool Equals(object? obj)
=> obj is Actor other && Equals(other);
public override int GetHashCode()
=> Address.GetHashCode();
public static bool operator ==(Actor lhs, Actor rhs)
=> lhs.Address == rhs.Address;
public static bool operator !=(Actor lhs, Actor rhs)
=> lhs.Address != rhs.Address;
/*
/// <summary> Only valid for characters. </summary>
public CharacterArmor GetArmor(EquipSlot slot)
=> ((CharacterArmor*)&AsCharacter->DrawData.Head)[slot.ToIndex()];
public CharacterWeapon GetMainhand()
=> new(AsCharacter->DrawData.Weapon(DrawDataContainer.WeaponSlot.MainHand).ModelId.Value);
public CharacterWeapon GetOffhand()
=> new(AsCharacter->DrawData.Weapon(DrawDataContainer.WeaponSlot.OffHand).ModelId.Value);
public Customize GetCustomize()
=> *(Customize*)&AsCharacter->DrawData.CustomizeData;
*/
public override string ToString()
=> $"0x{Address:X}";
}

View File

@@ -1,4 +1,6 @@
namespace CustomizePlus.GameData.Data;
using Penumbra.GameData.Interop;
namespace CustomizePlus.GameData.Data;
/// <summary>
/// A single actor with its label and the list of associated game objects.

View File

@@ -1,199 +0,0 @@
using System;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using Object = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Object;
using ObjectType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType;
namespace CustomizePlus.GameData.Data;
public readonly unsafe struct Model : IEquatable<Model>
{
private Model(nint address)
=> Address = address;
public readonly nint Address;
public static readonly Model Null = new(0);
public DrawObject* AsDrawObject
=> (DrawObject*)Address;
public CharacterBase* AsCharacterBase
=> (CharacterBase*)Address;
public Weapon* AsWeapon
=> (Weapon*)Address;
public Human* AsHuman
=> (Human*)Address;
public static implicit operator Model(nint? pointer)
=> new(pointer ?? nint.Zero);
public static implicit operator Model(Object* pointer)
=> new((nint)pointer);
public static implicit operator Model(DrawObject* pointer)
=> new((nint)pointer);
public static implicit operator Model(Human* pointer)
=> new((nint)pointer);
public static implicit operator Model(CharacterBase* pointer)
=> new((nint)pointer);
public static implicit operator nint(Model model)
=> model.Address;
public bool Valid
=> Address != nint.Zero;
public bool IsCharacterBase
=> Valid && AsDrawObject->Object.GetObjectType() == ObjectType.CharacterBase;
public bool IsHuman
=> IsCharacterBase && AsCharacterBase->GetModelType() == CharacterBase.ModelType.Human;
public bool IsWeapon
=> IsCharacterBase && AsCharacterBase->GetModelType() == CharacterBase.ModelType.Weapon;
public static implicit operator bool(Model actor)
=> actor.Address != nint.Zero;
public static bool operator true(Model actor)
=> actor.Address != nint.Zero;
public static bool operator false(Model actor)
=> actor.Address == nint.Zero;
public static bool operator !(Model actor)
=> actor.Address == nint.Zero;
public bool Equals(Model other)
=> Address == other.Address;
public override bool Equals(object? obj)
=> obj is Model other && Equals(other);
public override int GetHashCode()
=> Address.GetHashCode();
public static bool operator ==(Model lhs, Model rhs)
=> lhs.Address == rhs.Address;
public static bool operator !=(Model lhs, Model rhs)
=> lhs.Address != rhs.Address;
/*
/// <summary> Only valid for humans. </summary>
public CharacterArmor GetArmor(EquipSlot slot)
=> ((CharacterArmor*)&AsHuman->Head)[slot.ToIndex()];
public Customize GetCustomize()
=> *(Customize*)&AsHuman->Customize;
public (Model Address, CharacterWeapon Data) GetMainhand()
{
Model weapon = AsDrawObject->Object.ChildObject;
return !weapon.IsWeapon
? (Null, CharacterWeapon.Empty)
: (weapon, new CharacterWeapon(weapon.AsWeapon->ModelSetId, weapon.AsWeapon->SecondaryId, (Variant)weapon.AsWeapon->Variant,
(StainId)weapon.AsWeapon->ModelUnknown));
}
public (Model Address, CharacterWeapon Data) GetOffhand()
{
var mainhand = AsDrawObject->Object.ChildObject;
if (mainhand == null)
return (Null, CharacterWeapon.Empty);
Model offhand = mainhand->NextSiblingObject;
if (offhand == mainhand || !offhand.IsWeapon)
return (Null, CharacterWeapon.Empty);
return (offhand, new CharacterWeapon(offhand.AsWeapon->ModelSetId, offhand.AsWeapon->SecondaryId, (Variant)offhand.AsWeapon->Variant,
(StainId)offhand.AsWeapon->ModelUnknown));
}
/// <summary> Obtain the mainhand and offhand and their data by guesstimating which child object is which. </summary>
public (Model Mainhand, Model Offhand, CharacterWeapon MainData, CharacterWeapon OffData) GetWeapons()
{
var (first, second, count) = GetChildrenWeapons();
switch (count)
{
case 0: return (Null, Null, CharacterWeapon.Empty, CharacterWeapon.Empty);
case 1:
return (first, Null, new CharacterWeapon(first.AsWeapon->ModelSetId, first.AsWeapon->SecondaryId,
(Variant)first.AsWeapon->Variant,
(StainId)first.AsWeapon->ModelUnknown), CharacterWeapon.Empty);
default:
var (main, off) = DetermineMainhand(first, second);
var mainData = new CharacterWeapon(main.AsWeapon->ModelSetId, main.AsWeapon->SecondaryId, (Variant)main.AsWeapon->Variant,
(StainId)main.AsWeapon->ModelUnknown);
var offData = new CharacterWeapon(off.AsWeapon->ModelSetId, off.AsWeapon->SecondaryId, (Variant)off.AsWeapon->Variant,
(StainId)off.AsWeapon->ModelUnknown);
return (main, off, mainData, offData);
}
}
/// <summary> Obtain the mainhand and offhand and their data by using the drawdata container from the corresponding actor. </summary>
public (Model Mainhand, Model Offhand, CharacterWeapon MainData, CharacterWeapon OffData) GetWeapons(Actor actor)
{
if (!Valid || !actor.IsCharacter || actor.Model.Address != Address)
return (Null, Null, CharacterWeapon.Empty, CharacterWeapon.Empty);
Model main = actor.AsCharacter->DrawData.Weapon(DrawDataContainer.WeaponSlot.MainHand).DrawObject;
var mainData = CharacterWeapon.Empty;
if (main.IsWeapon)
mainData = new CharacterWeapon(main.AsWeapon->ModelSetId, main.AsWeapon->SecondaryId, (Variant)main.AsWeapon->Variant,
(StainId)main.AsWeapon->ModelUnknown);
else
main = Null;
Model off = actor.AsCharacter->DrawData.Weapon(DrawDataContainer.WeaponSlot.OffHand).DrawObject;
var offData = CharacterWeapon.Empty;
if (off.IsWeapon)
offData = new CharacterWeapon(off.AsWeapon->ModelSetId, off.AsWeapon->SecondaryId, (Variant)off.AsWeapon->Variant,
(StainId)off.AsWeapon->ModelUnknown);
else
off = Null;
return (main, off, mainData, offData);
}
private (Model, Model, int) GetChildrenWeapons()
{
Span<Model> weapons = stackalloc Model[2];
weapons[0] = Null;
weapons[1] = Null;
var count = 0;
if (!Valid || AsDrawObject->Object.ChildObject == null)
return (weapons[0], weapons[1], count);
Model starter = AsDrawObject->Object.ChildObject;
var iterator = starter;
do
{
if (iterator.IsWeapon)
weapons[count++] = iterator;
if (count == 2)
return (weapons[0], weapons[1], count);
iterator = iterator.AsDrawObject->Object.NextSiblingObject;
} while (iterator.Address != starter.Address);
return (weapons[0], weapons[1], count);
}
/// <summary> I don't know a safe way to do this but in experiments this worked.
/// The first uint at +0x8 was set to non-zero for the mainhand and zero for the offhand. </summary>
private static (Model Mainhand, Model Offhand) DetermineMainhand(Model first, Model second)
{
var discriminator1 = *(ulong*)(first.Address + 0x10);
var discriminator2 = *(ulong*)(second.Address + 0x10);
return discriminator1 == 0 && discriminator2 != 0 ? (second, first) : (first, second);
}
*/
public override string ToString()
=> $"0x{Address:X}";
}