Some more shuffling around.

This commit is contained in:
Ottermandias 2023-04-22 14:40:56 +02:00
parent a94c5ae7af
commit ce03fb59c8
9 changed files with 147 additions and 138 deletions

View file

@ -43,7 +43,7 @@ public class ActiveCollections : ISavable, IDisposable
Current = storage.DefaultNamed;
Default = storage.DefaultNamed;
Interface = storage.DefaultNamed;
Individuals = new IndividualCollections(actors.AwaitedService, config);
Individuals = new IndividualCollections(actors, config);
_communicator.CollectionChange.Subscribe(OnCollectionChange, -100);
LoadCollections();
UpdateCurrentCollectionInUse();
@ -396,7 +396,7 @@ public class ActiveCollections : ISavable, IDisposable
}
configChanged |= ActiveCollectionMigration.MigrateIndividualCollections(_storage, Individuals, jObject);
configChanged |= Individuals.ReadJObject(jObject[nameof(Individuals)] as JArray, _storage);
configChanged |= Individuals.ReadJObject(_saveService, this, jObject[nameof(Individuals)] as JArray, _storage);
// Save any changes.
if (configChanged)

View file

@ -40,7 +40,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
return true;
if (identifier.Retainer is not ActorIdentifier.RetainerType.Mannequin && _config.UseOwnerNameForCharacterCollection)
return CheckWorlds(_actorManager.GetCurrentPlayer(), out collection);
return CheckWorlds(_actorService.AwaitedService.GetCurrentPlayer(), out collection);
break;
}
@ -50,7 +50,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
return true;
// Handle generic NPC
var npcIdentifier = _actorManager.CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, ushort.MaxValue,
var npcIdentifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, ushort.MaxValue,
identifier.Kind, identifier.DataId);
if (npcIdentifier.IsValid && _individuals.TryGetValue(npcIdentifier, out collection))
return true;
@ -59,7 +59,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
if (!_config.UseOwnerNameForCharacterCollection)
return false;
identifier = _actorManager.CreateIndividualUnchecked(IdentifierType.Player, identifier.PlayerName, identifier.HomeWorld,
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(IdentifierType.Player, identifier.PlayerName, identifier.HomeWorld,
ObjectKind.None, uint.MaxValue);
return CheckWorlds(identifier, out collection);
}
@ -91,37 +91,37 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
if (identifier.Type != IdentifierType.Special)
return (identifier, SpecialResult.Invalid);
if (_actorManager.ResolvePartyBannerPlayer(identifier.Special, out var id))
if (_actorService.AwaitedService.ResolvePartyBannerPlayer(identifier.Special, out var id))
return (id, SpecialResult.PartyBanner);
if (_actorManager.ResolvePvPBannerPlayer(identifier.Special, out id))
if (_actorService.AwaitedService.ResolvePvPBannerPlayer(identifier.Special, out id))
return (id, SpecialResult.PvPBanner);
if (_actorManager.ResolveMahjongPlayer(identifier.Special, out id))
if (_actorService.AwaitedService.ResolveMahjongPlayer(identifier.Special, out id))
return (id, SpecialResult.Mahjong);
switch (identifier.Special)
{
case ScreenActor.CharacterScreen when _config.UseCharacterCollectionInMainWindow:
return (_actorManager.GetCurrentPlayer(), SpecialResult.CharacterScreen);
return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.CharacterScreen);
case ScreenActor.FittingRoom when _config.UseCharacterCollectionInTryOn:
return (_actorManager.GetCurrentPlayer(), SpecialResult.FittingRoom);
return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.FittingRoom);
case ScreenActor.DyePreview when _config.UseCharacterCollectionInTryOn:
return (_actorManager.GetCurrentPlayer(), SpecialResult.DyePreview);
return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.DyePreview);
case ScreenActor.Portrait when _config.UseCharacterCollectionsInCards:
return (_actorManager.GetCurrentPlayer(), SpecialResult.Portrait);
return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.Portrait);
case ScreenActor.ExamineScreen:
{
identifier = _actorManager.GetInspectPlayer();
identifier = _actorService.AwaitedService.GetInspectPlayer();
if (identifier.IsValid)
return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Inspect);
identifier = _actorManager.GetCardPlayer();
identifier = _actorService.AwaitedService.GetCardPlayer();
if (identifier.IsValid)
return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Card);
return _config.UseCharacterCollectionInTryOn
? (_actorManager.GetGlamourPlayer(), SpecialResult.Glamour)
? (_actorService.AwaitedService.GetGlamourPlayer(), SpecialResult.Glamour)
: (identifier, SpecialResult.Invalid);
}
default: return (identifier, SpecialResult.Invalid);
@ -129,10 +129,10 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
}
public bool TryGetCollection(GameObject? gameObject, out ModCollection? collection)
=> TryGetCollection(_actorManager.FromObject(gameObject, true, false, false), out collection);
=> TryGetCollection(_actorService.AwaitedService.FromObject(gameObject, true, false, false), out collection);
public unsafe bool TryGetCollection(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection)
=> TryGetCollection(_actorManager.FromObject(gameObject, out _, true, false, false), out collection);
=> TryGetCollection(_actorService.AwaitedService.FromObject(gameObject, out _, true, false, false), out collection);
private bool CheckWorlds(ActorIdentifier identifier, out ModCollection? collection)
{
@ -145,7 +145,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
if (_individuals.TryGetValue(identifier, out collection))
return true;
identifier = _actorManager.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, ushort.MaxValue, identifier.Kind,
identifier = _actorService.AwaitedService.CreateIndividualUnchecked(identifier.Type, identifier.PlayerName, ushort.MaxValue, identifier.Kind,
identifier.DataId);
if (identifier.IsValid && _individuals.TryGetValue(identifier, out collection))
return true;

View file

@ -6,6 +6,7 @@ using Dalamud.Interface.Internal.Notifications;
using Newtonsoft.Json.Linq;
using Penumbra.GameData.Actors;
using Penumbra.String;
using Penumbra.Util;
namespace Penumbra.Collections.Manager;
@ -25,7 +26,21 @@ public partial class IndividualCollections
return ret;
}
public bool ReadJObject(JArray? obj, CollectionStorage storage)
public bool ReadJObject(SaveService saver, ActiveCollections parent, JArray? obj, CollectionStorage storage)
{
if (_actorService.Valid)
return ReadJObjectInternal(obj, storage);
void Func()
{
if (ReadJObjectInternal(obj, storage))
saver.ImmediateSave(parent);
_actorService.FinishedCreation -= Func;
}
_actorService.FinishedCreation += Func;
return false;
}
private bool ReadJObjectInternal(JArray? obj, CollectionStorage storage)
{
if (obj == null)
return true;
@ -35,7 +50,7 @@ public partial class IndividualCollections
{
try
{
var identifier = _actorManager.FromJson(data as JObject);
var identifier = _actorService.AwaitedService.FromJson(data as JObject);
var group = GetGroup(identifier);
if (group.Length == 0 || group.Any(i => !i.IsValid))
{
@ -71,7 +86,6 @@ public partial class IndividualCollections
NotificationType.Error);
}
}
return changes;
}
@ -90,22 +104,22 @@ public partial class IndividualCollections
var kind = ObjectKind.None;
var lowerName = name.ToLowerInvariant();
// Prefer matching NPC names, fewer false positives than preferring players.
if (FindDataId(lowerName, _actorManager.Data.Companions, out var dataId))
if (FindDataId(lowerName, _actorService.AwaitedService.Data.Companions, out var dataId))
kind = ObjectKind.Companion;
else if (FindDataId(lowerName, _actorManager.Data.Mounts, out dataId))
else if (FindDataId(lowerName, _actorService.AwaitedService.Data.Mounts, out dataId))
kind = ObjectKind.MountType;
else if (FindDataId(lowerName, _actorManager.Data.BNpcs, out dataId))
else if (FindDataId(lowerName, _actorService.AwaitedService.Data.BNpcs, out dataId))
kind = ObjectKind.BattleNpc;
else if (FindDataId(lowerName, _actorManager.Data.ENpcs, out dataId))
else if (FindDataId(lowerName, _actorService.AwaitedService.Data.ENpcs, out dataId))
kind = ObjectKind.EventNpc;
var identifier = _actorManager.CreateNpc(kind, dataId);
var identifier = _actorService.AwaitedService.CreateNpc(kind, dataId);
if (identifier.IsValid)
{
// If the name corresponds to a valid npc, add it as a group. If this fails, notify users.
var group = GetGroup(identifier);
var ids = string.Join(", ", group.Select(i => i.DataId.ToString()));
if (Add($"{_actorManager.Data.ToName(kind, dataId)} ({kind.ToName()})", group, collection))
if (Add($"{_actorService.AwaitedService.Data.ToName(kind, dataId)} ({kind.ToName()})", group, collection))
Penumbra.Log.Information($"Migrated {name} ({kind.ToName()}) to NPC Identifiers [{ids}].");
else
Penumbra.ChatService.NotificationMessage(
@ -115,10 +129,10 @@ public partial class IndividualCollections
// If it is not a valid NPC name, check if it can be a player name.
else if (ActorManager.VerifyPlayerName(name))
{
identifier = _actorManager.CreatePlayer(ByteString.FromStringUnsafe(name, false), ushort.MaxValue);
identifier = _actorService.AwaitedService.CreatePlayer(ByteString.FromStringUnsafe(name, false), ushort.MaxValue);
var shortName = string.Join(" ", name.Split().Select(n => $"{n[0]}."));
// Try to migrate the player name without logging full names.
if (Add($"{name} ({_actorManager.Data.ToWorldName(identifier.HomeWorld)})", new[]
if (Add($"{name} ({_actorService.AwaitedService.Data.ToWorldName(identifier.HomeWorld)})", new[]
{
identifier,
}, collection))

View file

@ -13,24 +13,17 @@ namespace Penumbra.Collections.Manager;
public sealed partial class IndividualCollections
{
private readonly Configuration _config;
private readonly ActorManager _actorManager;
private readonly ActorService _actorService;
private readonly List<(string DisplayName, IReadOnlyList<ActorIdentifier> Identifiers, ModCollection Collection)> _assignments = new();
private readonly Dictionary<ActorIdentifier, ModCollection> _individuals = new();
public IReadOnlyList<(string DisplayName, IReadOnlyList<ActorIdentifier> Identifiers, ModCollection Collection)> Assignments
=> _assignments;
// TODO
public IndividualCollections(ActorService actorManager, Configuration config)
public IndividualCollections(ActorService actorService, Configuration config)
{
_config = config;
_actorManager = actorManager.AwaitedService;
}
public IndividualCollections(ActorManager actorManager, Configuration config)
{
_actorManager = actorManager;
_config = config;
_actorService = actorService;
}
public enum AddResult
@ -78,6 +71,7 @@ public sealed partial class IndividualCollections
{
identifiers = Array.Empty<ActorIdentifier>();
var manager = _actorService.AwaitedService;
switch (type)
{
case IdentifierType.Player:
@ -86,7 +80,7 @@ public sealed partial class IndividualCollections
identifiers = new[]
{
_actorManager.CreatePlayer(playerName, homeWorld),
manager.CreatePlayer(playerName, homeWorld),
};
break;
case IdentifierType.Retainer:
@ -95,18 +89,18 @@ public sealed partial class IndividualCollections
identifiers = new[]
{
_actorManager.CreateRetainer(retainerName, 0),
manager.CreateRetainer(retainerName, 0),
};
break;
case IdentifierType.Owned:
if (!ByteString.FromString(name, out var ownerName))
return AddResult.Invalid;
identifiers = dataIds.Select(id => _actorManager.CreateOwned(ownerName, homeWorld, kind, id)).ToArray();
identifiers = dataIds.Select(id => manager.CreateOwned(ownerName, homeWorld, kind, id)).ToArray();
break;
case IdentifierType.Npc:
identifiers = dataIds
.Select(id => _actorManager.CreateIndividual(IdentifierType.Npc, ByteString.Empty, ushort.MaxValue, kind, id)).ToArray();
.Select(id => manager.CreateIndividual(IdentifierType.Npc, ByteString.Empty, ushort.MaxValue, kind, id)).ToArray();
break;
default:
identifiers = Array.Empty<ActorIdentifier>();
@ -152,8 +146,8 @@ public sealed partial class IndividualCollections
{
identifier.CreatePermanent(),
},
IdentifierType.Owned => CreateNpcs(_actorManager, identifier.CreatePermanent()),
IdentifierType.Npc => CreateNpcs(_actorManager, identifier),
IdentifierType.Owned => CreateNpcs(_actorService.AwaitedService, identifier.CreatePermanent()),
IdentifierType.Npc => CreateNpcs(_actorService.AwaitedService, identifier),
_ => Array.Empty<ActorIdentifier>(),
};
}
@ -244,11 +238,11 @@ public sealed partial class IndividualCollections
{
return identifier.Type switch
{
IdentifierType.Player => $"{identifier.PlayerName} ({_actorManager.Data.ToWorldName(identifier.HomeWorld)})",
IdentifierType.Player => $"{identifier.PlayerName} ({_actorService.AwaitedService.Data.ToWorldName(identifier.HomeWorld)})",
IdentifierType.Retainer => $"{identifier.PlayerName} (Retainer)",
IdentifierType.Owned =>
$"{identifier.PlayerName} ({_actorManager.Data.ToWorldName(identifier.HomeWorld)})'s {_actorManager.Data.ToName(identifier.Kind, identifier.DataId)}",
IdentifierType.Npc => $"{_actorManager.Data.ToName(identifier.Kind, identifier.DataId)} ({identifier.Kind.ToName()})",
$"{identifier.PlayerName} ({_actorService.AwaitedService.Data.ToWorldName(identifier.HomeWorld)})'s {_actorService.AwaitedService.Data.ToName(identifier.Kind, identifier.DataId)}",
IdentifierType.Npc => $"{_actorService.AwaitedService.Data.ToName(identifier.Kind, identifier.DataId)} ({identifier.Kind.ToName()})",
_ => string.Empty,
};
}