mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +01:00
Fix some NPC item stuff and add new version of design base64, backward and forward compatible.
This commit is contained in:
parent
795e3b6845
commit
a40b710d25
7 changed files with 162 additions and 80 deletions
|
|
@ -6,6 +6,7 @@ using Glamourer.Services;
|
||||||
using Glamourer.Structs;
|
using Glamourer.Structs;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -398,11 +399,11 @@ public class DesignBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MigrateBase64(CustomizationService customizations, ItemManager items, string base64)
|
public void MigrateBase64(ItemManager items, HumanModelList humans, string base64)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DesignData = DesignBase64Migration.MigrateBase64(items, base64, out var equipFlags, out var customizeFlags,
|
DesignData = DesignBase64Migration.MigrateBase64(items, humans, base64, out var equipFlags, out var customizeFlags,
|
||||||
out var writeProtected,
|
out var writeProtected,
|
||||||
out var applyHat, out var applyVisor, out var applyWeapon);
|
out var applyHat, out var applyVisor, out var applyWeapon);
|
||||||
ApplyEquip = equipFlags;
|
ApplyEquip = equipFlags;
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,20 @@ using Glamourer.Customization;
|
||||||
using Glamourer.Services;
|
using Glamourer.Services;
|
||||||
using Glamourer.Structs;
|
using Glamourer.Structs;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
public static class DesignBase64Migration
|
public class DesignBase64Migration
|
||||||
{
|
{
|
||||||
public const int Base64Size = 91;
|
public const int Base64SizeV1 = 86;
|
||||||
|
public const int Base64SizeV2 = 91;
|
||||||
|
public const int Base64SizeV4 = 95;
|
||||||
|
|
||||||
public static DesignData MigrateBase64(ItemManager items, string base64, out EquipFlag equipFlags, out CustomizeFlag customizeFlags,
|
public static unsafe DesignData MigrateBase64(ItemManager items, HumanModelList humans, string base64, out EquipFlag equipFlags,
|
||||||
|
out CustomizeFlag customizeFlags,
|
||||||
out bool writeProtected, out bool applyHat, out bool applyVisor, out bool applyWeapon)
|
out bool writeProtected, out bool applyHat, out bool applyVisor, out bool applyWeapon)
|
||||||
{
|
{
|
||||||
static void CheckSize(int length, int requiredLength)
|
static void CheckSize(int length, int requiredLength)
|
||||||
|
|
@ -25,22 +29,22 @@ public static class DesignBase64Migration
|
||||||
byte applicationFlags;
|
byte applicationFlags;
|
||||||
ushort equipFlagsS;
|
ushort equipFlagsS;
|
||||||
var bytes = Convert.FromBase64String(base64);
|
var bytes = Convert.FromBase64String(base64);
|
||||||
applyHat = false;
|
applyHat = false;
|
||||||
applyVisor = false;
|
applyVisor = false;
|
||||||
applyWeapon = false;
|
applyWeapon = false;
|
||||||
var data = new DesignData();
|
var data = new DesignData();
|
||||||
switch (bytes[0])
|
switch (bytes[0])
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
CheckSize(bytes.Length, 86);
|
CheckSize(bytes.Length, Base64SizeV1);
|
||||||
applicationFlags = bytes[1];
|
applicationFlags = bytes[1];
|
||||||
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
CheckSize(bytes.Length, Base64Size);
|
CheckSize(bytes.Length, Base64SizeV2);
|
||||||
applicationFlags = bytes[1];
|
applicationFlags = bytes[1];
|
||||||
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||||
data.SetHatVisible((bytes[90] & 0x01) == 0);
|
data.SetHatVisible((bytes[90] & 0x01) == 0);
|
||||||
|
|
@ -48,6 +52,30 @@ public static class DesignBase64Migration
|
||||||
data.SetWeaponVisible((bytes[90] & 0x02) == 0);
|
data.SetWeaponVisible((bytes[90] & 0x02) == 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 3: // does not exist as old base64.
|
||||||
|
throw new Exception(
|
||||||
|
$"Can not parse Base64 string into design for migration:\n\tInvalid Version {bytes[0]} can not be migrated.");
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
CheckSize(bytes.Length, Base64SizeV4); // contains model id
|
||||||
|
applicationFlags = bytes[1];
|
||||||
|
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||||
|
data.SetHatVisible((bytes[90] & 0x01) == 0);
|
||||||
|
data.SetVisor((bytes[90] & 0x10) != 0);
|
||||||
|
data.SetWeaponVisible((bytes[90] & 0x02) == 0);
|
||||||
|
data.ModelId = (uint)bytes[91] | ((uint)bytes[92] << 8) | ((uint)bytes[93] << 16) | ((uint)bytes[94] << 24);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
bytes = bytes[..Base64SizeV4];
|
||||||
|
CheckSize(bytes.Length, Base64SizeV4); // contains model id
|
||||||
|
applicationFlags = bytes[1];
|
||||||
|
equipFlagsS = BitConverter.ToUInt16(bytes, 2);
|
||||||
|
data.SetHatVisible((bytes[90] & 0x01) == 0);
|
||||||
|
data.SetVisor((bytes[90] & 0x10) != 0);
|
||||||
|
data.SetWeaponVisible((bytes[90] & 0x02) == 0);
|
||||||
|
data.ModelId = (uint)bytes[91] | ((uint)bytes[92] << 8) | ((uint)bytes[93] << 16) | ((uint)bytes[94] << 24);
|
||||||
|
break;
|
||||||
default: throw new Exception($"Can not parse Base64 string into design for migration:\n\tInvalid Version {bytes[0]}.");
|
default: throw new Exception($"Can not parse Base64 string into design for migration:\n\tInvalid Version {bytes[0]}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,67 +96,71 @@ public static class DesignBase64Migration
|
||||||
equipFlags |= (equipFlagsS & flag) != 0 ? slot.ToFlag() | slot.ToStainFlag() : 0;
|
equipFlags |= (equipFlagsS & flag) != 0 ? slot.ToFlag() | slot.ToStainFlag() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe
|
fixed (byte* ptr = bytes)
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = bytes)
|
var cur = (CharacterWeapon*)(ptr + 30);
|
||||||
|
var eq = (CharacterArmor*)(cur + 2);
|
||||||
|
|
||||||
|
if (!humans.IsHuman(data.ModelId))
|
||||||
{
|
{
|
||||||
data.Customize.Load(*(Customize*)(ptr + 4));
|
data.LoadNonHuman(data.ModelId, *(Customize*)(ptr + 4), (nint)eq);
|
||||||
var cur = (CharacterWeapon*)(ptr + 30);
|
return data;
|
||||||
|
|
||||||
var eq = (CharacterArmor*)(cur + 2);
|
|
||||||
foreach (var (slot, idx) in EquipSlotExtensions.EqdpSlots.WithIndex())
|
|
||||||
{
|
|
||||||
var mdl = eq[idx];
|
|
||||||
var item = items.Identify(slot, mdl.Set, mdl.Variant);
|
|
||||||
if (!item.Valid)
|
|
||||||
throw new Exception($"Base64 string invalid, item could not be identified.");
|
|
||||||
|
|
||||||
data.SetItem(slot, item);
|
|
||||||
data.SetStain(slot, mdl.Stain);
|
|
||||||
}
|
|
||||||
|
|
||||||
var main = cur[0].Set.Value == 0 ? items.DefaultSword : items.Identify(EquipSlot.MainHand, cur[0].Set, cur[0].Type, (byte)cur[0].Variant);
|
|
||||||
if (!main.Valid)
|
|
||||||
throw new Exception($"Base64 string invalid, weapon could not be identified.");
|
|
||||||
|
|
||||||
data.SetItem(EquipSlot.MainHand, main);
|
|
||||||
data.SetStain(EquipSlot.MainHand, cur[0].Stain);
|
|
||||||
|
|
||||||
EquipItem off;
|
|
||||||
// Fist weapon hack
|
|
||||||
if (main.ModelId.Value is > 1600 and < 1651 && cur[1].Variant == 0)
|
|
||||||
{
|
|
||||||
off = items.Identify(EquipSlot.OffHand, (SetId)(main.ModelId.Value + 50), main.WeaponType, main.Variant, main.Type);
|
|
||||||
var gauntlet = items.Identify(EquipSlot.Hands, cur[1].Set, (byte)cur[1].Type);
|
|
||||||
if (!gauntlet.Valid)
|
|
||||||
throw new Exception($"Base64 string invalid, item could not be identified.");
|
|
||||||
|
|
||||||
data.SetItem(EquipSlot.Hands, gauntlet);
|
|
||||||
data.SetStain(EquipSlot.Hands, cur[0].Stain);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
off = cur[0].Set.Value == 0
|
|
||||||
? ItemManager.NothingItem(FullEquipType.Shield)
|
|
||||||
: items.Identify(EquipSlot.OffHand, cur[1].Set, cur[1].Type, (byte)cur[1].Variant, main.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (main.Type.ValidOffhand() != FullEquipType.Unknown && !off.Valid)
|
|
||||||
throw new Exception($"Base64 string invalid, weapon could not be identified.");
|
|
||||||
|
|
||||||
data.SetItem(EquipSlot.OffHand, off);
|
|
||||||
data.SetStain(EquipSlot.OffHand, cur[1].Stain);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
data.Customize.Load(*(Customize*)(ptr + 4));
|
||||||
|
foreach (var (slot, idx) in EquipSlotExtensions.EqdpSlots.WithIndex())
|
||||||
|
{
|
||||||
|
var mdl = eq[idx];
|
||||||
|
var item = items.Identify(slot, mdl.Set, mdl.Variant);
|
||||||
|
if (!item.Valid)
|
||||||
|
throw new Exception($"Base64 string invalid, item could not be identified.");
|
||||||
|
|
||||||
|
data.SetItem(slot, item);
|
||||||
|
data.SetStain(slot, mdl.Stain);
|
||||||
|
}
|
||||||
|
|
||||||
|
var main = cur[0].Set.Value == 0
|
||||||
|
? items.DefaultSword
|
||||||
|
: items.Identify(EquipSlot.MainHand, cur[0].Set, cur[0].Type, (byte)cur[0].Variant);
|
||||||
|
if (!main.Valid)
|
||||||
|
throw new Exception($"Base64 string invalid, weapon could not be identified.");
|
||||||
|
|
||||||
|
data.SetItem(EquipSlot.MainHand, main);
|
||||||
|
data.SetStain(EquipSlot.MainHand, cur[0].Stain);
|
||||||
|
|
||||||
|
EquipItem off;
|
||||||
|
// Fist weapon hack
|
||||||
|
if (main.ModelId.Value is > 1600 and < 1651 && cur[1].Variant == 0)
|
||||||
|
{
|
||||||
|
off = items.Identify(EquipSlot.OffHand, (SetId)(main.ModelId.Value + 50), main.WeaponType, main.Variant, main.Type);
|
||||||
|
var gauntlet = items.Identify(EquipSlot.Hands, cur[1].Set, (byte)cur[1].Type);
|
||||||
|
if (!gauntlet.Valid)
|
||||||
|
throw new Exception($"Base64 string invalid, item could not be identified.");
|
||||||
|
|
||||||
|
data.SetItem(EquipSlot.Hands, gauntlet);
|
||||||
|
data.SetStain(EquipSlot.Hands, cur[0].Stain);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
off = cur[0].Set.Value == 0
|
||||||
|
? ItemManager.NothingItem(FullEquipType.Shield)
|
||||||
|
: items.Identify(EquipSlot.OffHand, cur[1].Set, cur[1].Type, (byte)cur[1].Variant, main.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main.Type.ValidOffhand() != FullEquipType.Unknown && !off.Valid)
|
||||||
|
throw new Exception($"Base64 string invalid, weapon could not be identified.");
|
||||||
|
|
||||||
|
data.SetItem(EquipSlot.OffHand, off);
|
||||||
|
data.SetStain(EquipSlot.OffHand, cur[1].Stain);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe string CreateOldBase64(in DesignData save, EquipFlag equipFlags, CustomizeFlag customizeFlags,
|
public static unsafe string CreateOldBase64(in DesignData save, EquipFlag equipFlags, CustomizeFlag customizeFlags,
|
||||||
bool setHat, bool setVisor, bool setWeapon, bool writeProtected, float alpha = 1.0f)
|
bool setHat, bool setVisor, bool setWeapon, bool writeProtected, float alpha = 1.0f)
|
||||||
{
|
{
|
||||||
var data = stackalloc byte[Base64Size];
|
var data = stackalloc byte[Base64SizeV4];
|
||||||
data[0] = 2;
|
data[0] = 5;
|
||||||
data[1] = (byte)((customizeFlags == CustomizeFlagExtensions.All ? 0x01 : 0)
|
data[1] = (byte)((customizeFlags == CustomizeFlagExtensions.All ? 0x01 : 0)
|
||||||
| (save.IsWet() ? 0x02 : 0)
|
| (save.IsWet() ? 0x02 : 0)
|
||||||
| (setHat ? 0x04 : 0)
|
| (setHat ? 0x04 : 0)
|
||||||
|
|
@ -158,6 +190,11 @@ public static class DesignBase64Migration
|
||||||
| (save.IsVisorToggled() ? 0x10 : 0)
|
| (save.IsVisorToggled() ? 0x10 : 0)
|
||||||
| (save.IsWeaponVisible() ? 0x00 : 0x02));
|
| (save.IsWeaponVisible() ? 0x00 : 0x02));
|
||||||
|
|
||||||
return Convert.ToBase64String(new Span<byte>(data, Base64Size));
|
data[91] = (byte)save.ModelId;
|
||||||
|
data[92] = (byte)(save.ModelId >> 8);
|
||||||
|
data[93] = (byte)(save.ModelId >> 16);
|
||||||
|
data[94] = (byte)(save.ModelId >> 24);
|
||||||
|
|
||||||
|
return Convert.ToBase64String(new Span<byte>(data, Base64SizeV4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,26 @@ using Glamourer.Structs;
|
||||||
using Glamourer.Utility;
|
using Glamourer.Utility;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
|
|
||||||
namespace Glamourer.Designs;
|
namespace Glamourer.Designs;
|
||||||
|
|
||||||
public class DesignConverter
|
public class DesignConverter
|
||||||
{
|
{
|
||||||
public const byte Version = 3;
|
public const byte Version = 5;
|
||||||
|
|
||||||
private readonly ItemManager _items;
|
private readonly ItemManager _items;
|
||||||
private readonly DesignManager _designs;
|
private readonly DesignManager _designs;
|
||||||
private readonly CustomizationService _customize;
|
private readonly CustomizationService _customize;
|
||||||
|
private readonly HumanModelList _humans;
|
||||||
|
|
||||||
public DesignConverter(ItemManager items, DesignManager designs, CustomizationService customize)
|
public DesignConverter(ItemManager items, DesignManager designs, CustomizationService customize, HumanModelList humans)
|
||||||
{
|
{
|
||||||
_items = items;
|
_items = items;
|
||||||
_designs = designs;
|
_designs = designs;
|
||||||
_customize = customize;
|
_customize = customize;
|
||||||
|
_humans = humans;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JObject ShareJObject(DesignBase design)
|
public JObject ShareJObject(DesignBase design)
|
||||||
|
|
@ -40,13 +43,16 @@ public class DesignConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ShareBase64(Design design)
|
public string ShareBase64(Design design)
|
||||||
=> ShareBase64(ShareJObject(design));
|
=> ShareBackwardCompatible(ShareJObject(design), design);
|
||||||
|
|
||||||
public string ShareBase64(DesignBase design)
|
public string ShareBase64(DesignBase design)
|
||||||
=> ShareBase64(ShareJObject(design));
|
=> ShareBackwardCompatible(ShareJObject(design), design);
|
||||||
|
|
||||||
public string ShareBase64(ActorState state)
|
public string ShareBase64(ActorState state)
|
||||||
=> ShareBase64(ShareJObject(state, EquipFlagExtensions.All, CustomizeFlagExtensions.All));
|
{
|
||||||
|
var design = Convert(state, EquipFlagExtensions.All, CustomizeFlagExtensions.All);
|
||||||
|
return ShareBackwardCompatible(ShareJObject(design), design);
|
||||||
|
}
|
||||||
|
|
||||||
public DesignBase Convert(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags)
|
public DesignBase Convert(ActorState state, EquipFlag equipFlags, CustomizeFlag customizeFlags)
|
||||||
{
|
{
|
||||||
|
|
@ -79,17 +85,31 @@ public class DesignConverter
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
|
case 4:
|
||||||
ret = _designs.CreateTemporary();
|
ret = _designs.CreateTemporary();
|
||||||
ret.MigrateBase64(_customize, _items, base64);
|
ret.MigrateBase64(_items, _humans, base64);
|
||||||
break;
|
break;
|
||||||
case Version:
|
case 3:
|
||||||
|
{
|
||||||
version = bytes.DecompressToString(out var decompressed);
|
version = bytes.DecompressToString(out var decompressed);
|
||||||
var jObj2 = JObject.Parse(decompressed);
|
var jObj2 = JObject.Parse(decompressed);
|
||||||
|
Debug.Assert(version == 3);
|
||||||
|
ret = jObj2["Identifier"] != null
|
||||||
|
? Design.LoadDesign(_customize, _items, jObj2)
|
||||||
|
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Version:
|
||||||
|
{
|
||||||
|
bytes = bytes[DesignBase64Migration.Base64SizeV4..];
|
||||||
|
version = bytes.DecompressToString(out var decompressed);
|
||||||
|
var jObj2 = JObject.Parse(decompressed);
|
||||||
Debug.Assert(version == Version);
|
Debug.Assert(version == Version);
|
||||||
ret = jObj2["Identifier"] != null
|
ret = jObj2["Identifier"] != null
|
||||||
? Design.LoadDesign(_customize, _items, jObj2)
|
? Design.LoadDesign(_customize, _items, jObj2)
|
||||||
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
: DesignBase.LoadDesignBase(_customize, _items, jObj2);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: throw new Exception($"Unknown Version {bytes[0]}.");
|
default: throw new Exception($"Unknown Version {bytes[0]}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -122,4 +142,17 @@ public class DesignConverter
|
||||||
var compressed = json.Compress(Version);
|
var compressed = json.Compress(Version);
|
||||||
return System.Convert.ToBase64String(compressed);
|
return System.Convert.ToBase64String(compressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ShareBackwardCompatible(JObject jObject, DesignBase design)
|
||||||
|
{
|
||||||
|
var oldBase64 = DesignBase64Migration.CreateOldBase64(design.DesignData, design.ApplyEquip, design.ApplyCustomize,
|
||||||
|
design.DoApplyHatVisible(), design.DoApplyVisorToggle(), design.DoApplyWeaponVisible(), design.WriteProtected(), 1f);
|
||||||
|
var oldBytes = System.Convert.FromBase64String(oldBase64);
|
||||||
|
var json = jObject.ToString(Formatting.None);
|
||||||
|
var compressed = json.Compress(Version);
|
||||||
|
var bytes = new byte[oldBytes.Length + compressed.Length];
|
||||||
|
oldBytes.CopyTo(bytes, 0);
|
||||||
|
compressed.CopyTo(bytes, oldBytes.Length);
|
||||||
|
return System.Convert.ToBase64String(bytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using Glamourer.State;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -20,6 +21,7 @@ public class DesignManager
|
||||||
{
|
{
|
||||||
private readonly CustomizationService _customizations;
|
private readonly CustomizationService _customizations;
|
||||||
private readonly ItemManager _items;
|
private readonly ItemManager _items;
|
||||||
|
private readonly HumanModelList _humans;
|
||||||
private readonly SaveService _saveService;
|
private readonly SaveService _saveService;
|
||||||
private readonly DesignChanged _event;
|
private readonly DesignChanged _event;
|
||||||
private readonly List<Design> _designs = new();
|
private readonly List<Design> _designs = new();
|
||||||
|
|
@ -28,12 +30,13 @@ public class DesignManager
|
||||||
=> _designs;
|
=> _designs;
|
||||||
|
|
||||||
public DesignManager(SaveService saveService, ItemManager items, CustomizationService customizations,
|
public DesignManager(SaveService saveService, ItemManager items, CustomizationService customizations,
|
||||||
DesignChanged @event)
|
DesignChanged @event, HumanModelList humans)
|
||||||
{
|
{
|
||||||
_saveService = saveService;
|
_saveService = saveService;
|
||||||
_items = items;
|
_items = items;
|
||||||
_customizations = customizations;
|
_customizations = customizations;
|
||||||
_event = @event;
|
_event = @event;
|
||||||
|
_humans = humans;
|
||||||
CreateDesignFolder(saveService);
|
CreateDesignFolder(saveService);
|
||||||
LoadDesigns();
|
LoadDesigns();
|
||||||
MigrateOldDesigns();
|
MigrateOldDesigns();
|
||||||
|
|
@ -519,7 +522,7 @@ public class DesignManager
|
||||||
Identifier = CreateNewGuid(),
|
Identifier = CreateNewGuid(),
|
||||||
Name = actualName,
|
Name = actualName,
|
||||||
};
|
};
|
||||||
design.MigrateBase64(_customizations, _items, base64);
|
design.MigrateBase64(_items, _humans, base64);
|
||||||
if (!_designs.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate))
|
if (!_designs.Any(d => d.Name == design.Name && d.CreationDate == design.CreationDate))
|
||||||
{
|
{
|
||||||
Add(design, $"Migrated old design to {design.Identifier}.");
|
Add(design, $"Migrated old design to {design.Identifier}.");
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ using OtterGui;
|
||||||
using OtterGui.Raii;
|
using OtterGui.Raii;
|
||||||
using OtterGui.Widgets;
|
using OtterGui.Widgets;
|
||||||
using Penumbra.Api.Enums;
|
using Penumbra.Api.Enums;
|
||||||
|
using Penumbra.GameData.Data;
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
|
|
||||||
|
|
@ -62,6 +63,7 @@ public unsafe class DebugTab : ITab
|
||||||
private readonly DesignFileSystem _designFileSystem;
|
private readonly DesignFileSystem _designFileSystem;
|
||||||
private readonly AutoDesignManager _autoDesignManager;
|
private readonly AutoDesignManager _autoDesignManager;
|
||||||
private readonly DesignConverter _designConverter;
|
private readonly DesignConverter _designConverter;
|
||||||
|
private readonly HumanModelList _humans;
|
||||||
|
|
||||||
private readonly PenumbraChangedItemTooltip _penumbraTooltip;
|
private readonly PenumbraChangedItemTooltip _penumbraTooltip;
|
||||||
|
|
||||||
|
|
@ -78,7 +80,8 @@ public unsafe class DebugTab : ITab
|
||||||
DesignFileSystem designFileSystem, DesignManager designManager, StateManager state, Configuration config,
|
DesignFileSystem designFileSystem, DesignManager designManager, StateManager state, Configuration config,
|
||||||
PenumbraChangedItemTooltip penumbraTooltip, MetaService metaService, GlamourerIpc ipc, DalamudPluginInterface pluginInterface,
|
PenumbraChangedItemTooltip penumbraTooltip, MetaService metaService, GlamourerIpc ipc, DalamudPluginInterface pluginInterface,
|
||||||
AutoDesignManager autoDesignManager, JobService jobs, CodeService code, CustomizeUnlockManager customizeUnlocks,
|
AutoDesignManager autoDesignManager, JobService jobs, CodeService code, CustomizeUnlockManager customizeUnlocks,
|
||||||
ItemUnlockManager itemUnlocks, DesignConverter designConverter, DatFileService datFileService, InventoryService inventoryService)
|
ItemUnlockManager itemUnlocks, DesignConverter designConverter, DatFileService datFileService, InventoryService inventoryService,
|
||||||
|
HumanModelList humans)
|
||||||
{
|
{
|
||||||
_changeCustomizeService = changeCustomizeService;
|
_changeCustomizeService = changeCustomizeService;
|
||||||
_visorService = visorService;
|
_visorService = visorService;
|
||||||
|
|
@ -106,6 +109,7 @@ public unsafe class DebugTab : ITab
|
||||||
_designConverter = designConverter;
|
_designConverter = designConverter;
|
||||||
_datFileService = datFileService;
|
_datFileService = datFileService;
|
||||||
_inventoryService = inventoryService;
|
_inventoryService = inventoryService;
|
||||||
|
_humans = humans;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReadOnlySpan<byte> Label
|
public ReadOnlySpan<byte> Label
|
||||||
|
|
@ -639,7 +643,7 @@ public unsafe class DebugTab : ITab
|
||||||
var identified = _items.Identify(slot, (SetId)_setId, (byte)_variant);
|
var identified = _items.Identify(slot, (SetId)_setId, (byte)_variant);
|
||||||
Text(identified.Name);
|
Text(identified.Name);
|
||||||
ImGuiUtil.HoverTooltip(string.Join("\n",
|
ImGuiUtil.HoverTooltip(string.Join("\n",
|
||||||
_items.IdentifierService.AwaitedService.Identify((SetId)_setId, (ushort)_variant, slot).Select(i => i.Name)));
|
_items.IdentifierService.AwaitedService.Identify((SetId)_setId, (ushort)_variant, slot).Select(i => $"{i.Name} {i.Id} {i.ItemId} {i.IconId}")));
|
||||||
}
|
}
|
||||||
|
|
||||||
var weapon = _items.Identify(EquipSlot.MainHand, (SetId)_setId, (WeaponType)_secondaryId, (byte)_variant);
|
var weapon = _items.Identify(EquipSlot.MainHand, (SetId)_setId, (WeaponType)_secondaryId, (byte)_variant);
|
||||||
|
|
@ -939,7 +943,8 @@ public unsafe class DebugTab : ITab
|
||||||
if (_parse64Failure == null)
|
if (_parse64Failure == null)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_parse64 = DesignBase64Migration.MigrateBase64(_items, _base64, out var ef, out var cf, out var wp, out var ah, out var av,
|
_parse64 = DesignBase64Migration.MigrateBase64(_items, _humans, _base64, out var ef, out var cf, out var wp, out var ah,
|
||||||
|
out var av,
|
||||||
out var aw);
|
out var aw);
|
||||||
_restore = DesignBase64Migration.CreateOldBase64(in _parse64, ef, cf, ah, av, aw, wp);
|
_restore = DesignBase64Migration.CreateOldBase64(in _parse64, ef, cf, ah, av, aw, wp);
|
||||||
_restoreBytes = Convert.FromBase64String(_restore);
|
_restoreBytes = Convert.FromBase64String(_restore);
|
||||||
|
|
@ -1035,6 +1040,9 @@ public unsafe class DebugTab : ITab
|
||||||
{
|
{
|
||||||
_clipboardText = ImGui.GetClipboardText();
|
_clipboardText = ImGui.GetClipboardText();
|
||||||
_clipboardData = Convert.FromBase64String(_clipboardText);
|
_clipboardData = Convert.FromBase64String(_clipboardText);
|
||||||
|
_version = _clipboardData[0];
|
||||||
|
if (_version == 5)
|
||||||
|
_clipboardData = _clipboardData[DesignBase64Migration.Base64SizeV4..];
|
||||||
_version = _clipboardData.Decompress(out _dataUncompressed);
|
_version = _clipboardData.Decompress(out _dataUncompressed);
|
||||||
_textUncompressed = Encoding.UTF8.GetString(_dataUncompressed);
|
_textUncompressed = Encoding.UTF8.GetString(_dataUncompressed);
|
||||||
_json = JObject.Parse(_textUncompressed);
|
_json = JObject.Parse(_textUncompressed);
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ public class ItemManager : IDisposable
|
||||||
return SmallClothesItem(slot);
|
return SmallClothesItem(slot);
|
||||||
|
|
||||||
if (!ItemService.AwaitedService.TryGetValue(itemId, slot, out var item))
|
if (!ItemService.AwaitedService.TryGetValue(itemId, slot, out var item))
|
||||||
return new EquipItem(string.Intern($"Unknown #{itemId}"), itemId, 0, 0, 0, 0, 0);
|
return EquipItem.FromId(itemId);
|
||||||
|
|
||||||
if (item.Type.ToSlot() != slot)
|
if (item.Type.ToSlot() != slot)
|
||||||
return new EquipItem(string.Intern($"Invalid #{itemId}"), itemId, item.IconId, item.ModelId, item.WeaponType, item.Variant, 0);
|
return new EquipItem(string.Intern($"Invalid #{itemId}"), itemId, item.IconId, item.ModelId, item.WeaponType, item.Variant, 0);
|
||||||
|
|
@ -89,7 +89,7 @@ public class ItemManager : IDisposable
|
||||||
return NothingItem(type);
|
return NothingItem(type);
|
||||||
|
|
||||||
if (!ItemService.AwaitedService.TryGetValue(itemId, type is FullEquipType.Shield ? EquipSlot.MainHand : EquipSlot.OffHand, out var item))
|
if (!ItemService.AwaitedService.TryGetValue(itemId, type is FullEquipType.Shield ? EquipSlot.MainHand : EquipSlot.OffHand, out var item))
|
||||||
return new EquipItem(string.Intern($"Unknown #{itemId}"), itemId, 0, 0, 0, 0, 0);
|
return EquipItem.FromId(itemId);
|
||||||
|
|
||||||
if (item.Type != type)
|
if (item.Type != type)
|
||||||
return new EquipItem(string.Intern($"Invalid #{itemId}"), itemId, item.IconId, item.ModelId, item.WeaponType, item.Variant, 0);
|
return new EquipItem(string.Intern($"Invalid #{itemId}"), itemId, item.IconId, item.ModelId, item.WeaponType, item.Variant, 0);
|
||||||
|
|
@ -111,7 +111,7 @@ public class ItemManager : IDisposable
|
||||||
var item = IdentifierService.AwaitedService.Identify(id, variant, slot).FirstOrDefault();
|
var item = IdentifierService.AwaitedService.Identify(id, variant, slot).FirstOrDefault();
|
||||||
return item.Valid
|
return item.Valid
|
||||||
? item
|
? item
|
||||||
: new EquipItem($"Unknown ({id.Value}-{variant})", 0, 0, id, 0, variant, slot.ToEquipType());
|
: EquipItem.FromIds(0, 0, id, 0, variant, slot.ToEquipType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit eeb55916372432aa0b5936cc8648657fd4b3447a
|
Subproject commit 98bd4e9946ded20cb5d54182883e73f344fe2d26
|
||||||
Loading…
Add table
Add a link
Reference in a new issue