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

@ -145,10 +145,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
_redrawService = redrawService; _redrawService = redrawService;
_modFileSystem = modFileSystem; _modFileSystem = modFileSystem;
_configWindow = configWindow; _configWindow = configWindow;
_lumina = _dalamud.GameData.GameData;
_lumina = (Lumina.GameData?)_dalamud.GameData.GetType()
.GetField("gameData", BindingFlags.Instance | BindingFlags.NonPublic)
?.GetValue(_dalamud.GameData);
_resourceLoader.ResourceLoaded += OnResourceLoaded; _resourceLoader.ResourceLoaded += OnResourceLoaded;
_communicator.ModPathChanged.Subscribe(ModPathChangeSubscriber); _communicator.ModPathChanged.Subscribe(ModPathChangeSubscriber);

View file

@ -43,7 +43,7 @@ public class ActiveCollections : ISavable, IDisposable
Current = storage.DefaultNamed; Current = storage.DefaultNamed;
Default = storage.DefaultNamed; Default = storage.DefaultNamed;
Interface = storage.DefaultNamed; Interface = storage.DefaultNamed;
Individuals = new IndividualCollections(actors.AwaitedService, config); Individuals = new IndividualCollections(actors, config);
_communicator.CollectionChange.Subscribe(OnCollectionChange, -100); _communicator.CollectionChange.Subscribe(OnCollectionChange, -100);
LoadCollections(); LoadCollections();
UpdateCurrentCollectionInUse(); UpdateCurrentCollectionInUse();
@ -396,7 +396,7 @@ public class ActiveCollections : ISavable, IDisposable
} }
configChanged |= ActiveCollectionMigration.MigrateIndividualCollections(_storage, Individuals, jObject); 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. // Save any changes.
if (configChanged) if (configChanged)

View file

@ -40,7 +40,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
return true; return true;
if (identifier.Retainer is not ActorIdentifier.RetainerType.Mannequin && _config.UseOwnerNameForCharacterCollection) if (identifier.Retainer is not ActorIdentifier.RetainerType.Mannequin && _config.UseOwnerNameForCharacterCollection)
return CheckWorlds(_actorManager.GetCurrentPlayer(), out collection); return CheckWorlds(_actorService.AwaitedService.GetCurrentPlayer(), out collection);
break; break;
} }
@ -50,7 +50,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
return true; return true;
// Handle generic NPC // 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); identifier.Kind, identifier.DataId);
if (npcIdentifier.IsValid && _individuals.TryGetValue(npcIdentifier, out collection)) if (npcIdentifier.IsValid && _individuals.TryGetValue(npcIdentifier, out collection))
return true; return true;
@ -59,7 +59,7 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
if (!_config.UseOwnerNameForCharacterCollection) if (!_config.UseOwnerNameForCharacterCollection)
return false; 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); ObjectKind.None, uint.MaxValue);
return CheckWorlds(identifier, out collection); return CheckWorlds(identifier, out collection);
} }
@ -91,37 +91,37 @@ public sealed partial class IndividualCollections : IReadOnlyList<(string Displa
if (identifier.Type != IdentifierType.Special) if (identifier.Type != IdentifierType.Special)
return (identifier, SpecialResult.Invalid); 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); return (id, SpecialResult.PartyBanner);
if (_actorManager.ResolvePvPBannerPlayer(identifier.Special, out id)) if (_actorService.AwaitedService.ResolvePvPBannerPlayer(identifier.Special, out id))
return (id, SpecialResult.PvPBanner); return (id, SpecialResult.PvPBanner);
if (_actorManager.ResolveMahjongPlayer(identifier.Special, out id)) if (_actorService.AwaitedService.ResolveMahjongPlayer(identifier.Special, out id))
return (id, SpecialResult.Mahjong); return (id, SpecialResult.Mahjong);
switch (identifier.Special) switch (identifier.Special)
{ {
case ScreenActor.CharacterScreen when _config.UseCharacterCollectionInMainWindow: case ScreenActor.CharacterScreen when _config.UseCharacterCollectionInMainWindow:
return (_actorManager.GetCurrentPlayer(), SpecialResult.CharacterScreen); return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.CharacterScreen);
case ScreenActor.FittingRoom when _config.UseCharacterCollectionInTryOn: case ScreenActor.FittingRoom when _config.UseCharacterCollectionInTryOn:
return (_actorManager.GetCurrentPlayer(), SpecialResult.FittingRoom); return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.FittingRoom);
case ScreenActor.DyePreview when _config.UseCharacterCollectionInTryOn: case ScreenActor.DyePreview when _config.UseCharacterCollectionInTryOn:
return (_actorManager.GetCurrentPlayer(), SpecialResult.DyePreview); return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.DyePreview);
case ScreenActor.Portrait when _config.UseCharacterCollectionsInCards: case ScreenActor.Portrait when _config.UseCharacterCollectionsInCards:
return (_actorManager.GetCurrentPlayer(), SpecialResult.Portrait); return (_actorService.AwaitedService.GetCurrentPlayer(), SpecialResult.Portrait);
case ScreenActor.ExamineScreen: case ScreenActor.ExamineScreen:
{ {
identifier = _actorManager.GetInspectPlayer(); identifier = _actorService.AwaitedService.GetInspectPlayer();
if (identifier.IsValid) if (identifier.IsValid)
return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Inspect); return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Inspect);
identifier = _actorManager.GetCardPlayer(); identifier = _actorService.AwaitedService.GetCardPlayer();
if (identifier.IsValid) if (identifier.IsValid)
return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Card); return (_config.UseCharacterCollectionInInspect ? identifier : ActorIdentifier.Invalid, SpecialResult.Card);
return _config.UseCharacterCollectionInTryOn return _config.UseCharacterCollectionInTryOn
? (_actorManager.GetGlamourPlayer(), SpecialResult.Glamour) ? (_actorService.AwaitedService.GetGlamourPlayer(), SpecialResult.Glamour)
: (identifier, SpecialResult.Invalid); : (identifier, SpecialResult.Invalid);
} }
default: return (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) 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) 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) 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)) if (_individuals.TryGetValue(identifier, out collection))
return true; 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); identifier.DataId);
if (identifier.IsValid && _individuals.TryGetValue(identifier, out collection)) if (identifier.IsValid && _individuals.TryGetValue(identifier, out collection))
return true; return true;

View file

@ -6,6 +6,7 @@ using Dalamud.Interface.Internal.Notifications;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Penumbra.GameData.Actors; using Penumbra.GameData.Actors;
using Penumbra.String; using Penumbra.String;
using Penumbra.Util;
namespace Penumbra.Collections.Manager; namespace Penumbra.Collections.Manager;
@ -25,7 +26,21 @@ public partial class IndividualCollections
return ret; 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) if (obj == null)
return true; return true;
@ -35,7 +50,7 @@ public partial class IndividualCollections
{ {
try try
{ {
var identifier = _actorManager.FromJson(data as JObject); var identifier = _actorService.AwaitedService.FromJson(data as JObject);
var group = GetGroup(identifier); var group = GetGroup(identifier);
if (group.Length == 0 || group.Any(i => !i.IsValid)) if (group.Length == 0 || group.Any(i => !i.IsValid))
{ {
@ -71,7 +86,6 @@ public partial class IndividualCollections
NotificationType.Error); NotificationType.Error);
} }
} }
return changes; return changes;
} }
@ -90,22 +104,22 @@ public partial class IndividualCollections
var kind = ObjectKind.None; var kind = ObjectKind.None;
var lowerName = name.ToLowerInvariant(); var lowerName = name.ToLowerInvariant();
// Prefer matching NPC names, fewer false positives than preferring players. // 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; 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; 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; 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; kind = ObjectKind.EventNpc;
var identifier = _actorManager.CreateNpc(kind, dataId); var identifier = _actorService.AwaitedService.CreateNpc(kind, dataId);
if (identifier.IsValid) if (identifier.IsValid)
{ {
// If the name corresponds to a valid npc, add it as a group. If this fails, notify users. // If the name corresponds to a valid npc, add it as a group. If this fails, notify users.
var group = GetGroup(identifier); var group = GetGroup(identifier);
var ids = string.Join(", ", group.Select(i => i.DataId.ToString())); 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}]."); Penumbra.Log.Information($"Migrated {name} ({kind.ToName()}) to NPC Identifiers [{ids}].");
else else
Penumbra.ChatService.NotificationMessage( 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. // If it is not a valid NPC name, check if it can be a player name.
else if (ActorManager.VerifyPlayerName(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]}.")); var shortName = string.Join(" ", name.Split().Select(n => $"{n[0]}."));
// Try to migrate the player name without logging full names. // 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, identifier,
}, collection)) }, collection))

View file

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

View file

@ -44,31 +44,33 @@ public class Penumbra : IDalamudPlugin
private PenumbraWindowSystem? _windowSystem; private PenumbraWindowSystem? _windowSystem;
private bool _disposed; private bool _disposed;
private readonly ServiceManager _tmp; private readonly ServiceProvider _services;
public Penumbra(DalamudPluginInterface pluginInterface) public Penumbra(DalamudPluginInterface pluginInterface)
{ {
try try
{ {
_tmp = new ServiceManager(this, pluginInterface, Log); var startTimer = new StartTracker();
ChatService = _tmp.Services.GetRequiredService<ChatService>(); using var timer = startTimer.Measure(StartTimeType.Total);
_validityChecker = _tmp.Services.GetRequiredService<ValidityChecker>(); _services = ServiceManager.CreateProvider(this, pluginInterface, Log, startTimer);
_tmp.Services.GetRequiredService<BackupService>(); // Initialize because not required anywhere else. ChatService = _services.GetRequiredService<ChatService>();
_config = _tmp.Services.GetRequiredService<Configuration>(); _validityChecker = _services.GetRequiredService<ValidityChecker>();
_characterUtility = _tmp.Services.GetRequiredService<CharacterUtility>(); _services.GetRequiredService<BackupService>(); // Initialize because not required anywhere else.
_tempMods = _tmp.Services.GetRequiredService<TempModManager>(); _config = _services.GetRequiredService<Configuration>();
_residentResources = _tmp.Services.GetRequiredService<ResidentResourceManager>(); _characterUtility = _services.GetRequiredService<CharacterUtility>();
_tmp.Services.GetRequiredService<ResourceManagerService>(); // Initialize because not required anywhere else. _tempMods = _services.GetRequiredService<TempModManager>();
_modManager = _tmp.Services.GetRequiredService<ModManager>(); _residentResources = _services.GetRequiredService<ResidentResourceManager>();
_collectionManager = _tmp.Services.GetRequiredService<CollectionManager>(); _services.GetRequiredService<ResourceManagerService>(); // Initialize because not required anywhere else.
_tempCollections = _tmp.Services.GetRequiredService<TempCollectionManager>(); _modManager = _services.GetRequiredService<ModManager>();
_redrawService = _tmp.Services.GetRequiredService<RedrawService>(); _collectionManager = _services.GetRequiredService<CollectionManager>();
_communicatorService = _tmp.Services.GetRequiredService<CommunicatorService>(); _tempCollections = _services.GetRequiredService<TempCollectionManager>();
_tmp.Services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else. _redrawService = _services.GetRequiredService<RedrawService>();
_tmp.Services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else. _communicatorService = _services.GetRequiredService<CommunicatorService>();
using (var t = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver)) _services.GetRequiredService<ResourceService>(); // Initialize because not required anywhere else.
_services.GetRequiredService<ModCacheManager>(); // Initialize because not required anywhere else.
using (var t = _services.GetRequiredService<StartTracker>().Measure(StartTimeType.PathResolver))
{ {
_tmp.Services.GetRequiredService<PathResolver>(); _services.GetRequiredService<PathResolver>();
} }
SetupInterface(); SetupInterface();
@ -92,9 +94,9 @@ public class Penumbra : IDalamudPlugin
private void SetupApi() private void SetupApi()
{ {
using var timer = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Api); using var timer = _services.GetRequiredService<StartTracker>().Measure(StartTimeType.Api);
var api = _tmp.Services.GetRequiredService<IPenumbraApi>(); var api = _services.GetRequiredService<IPenumbraApi>();
_tmp.Services.GetRequiredService<PenumbraIpcProviders>(); _services.GetRequiredService<PenumbraIpcProviders>();
api.ChangedItemTooltip += it => api.ChangedItemTooltip += it =>
{ {
if (it is Item) if (it is Item)
@ -111,10 +113,10 @@ public class Penumbra : IDalamudPlugin
{ {
Task.Run(() => Task.Run(() =>
{ {
using var tInterface = _tmp.Services.GetRequiredService<StartTracker>().Measure(StartTimeType.Interface); using var tInterface = _services.GetRequiredService<StartTracker>().Measure(StartTimeType.Interface);
var system = _tmp.Services.GetRequiredService<PenumbraWindowSystem>(); var system = _services.GetRequiredService<PenumbraWindowSystem>();
system.Window.Setup(this, _tmp.Services.GetRequiredService<ConfigTabBar>()); system.Window.Setup(this, _services.GetRequiredService<ConfigTabBar>());
_tmp.Services.GetRequiredService<CommandHandler>(); _services.GetRequiredService<CommandHandler>();
if (!_disposed) if (!_disposed)
_windowSystem = system; _windowSystem = system;
else else
@ -162,7 +164,7 @@ public class Penumbra : IDalamudPlugin
if (_disposed) if (_disposed)
return; return;
_tmp?.Dispose(); _services?.Dispose();
_disposed = true; _disposed = true;
} }
@ -183,7 +185,7 @@ public class Penumbra : IDalamudPlugin
sb.Append($"> **`Auto-Deduplication: `** {_config.AutoDeduplicateOnImport}\n"); sb.Append($"> **`Auto-Deduplication: `** {_config.AutoDeduplicateOnImport}\n");
sb.Append($"> **`Debug Mode: `** {_config.DebugMode}\n"); sb.Append($"> **`Debug Mode: `** {_config.DebugMode}\n");
sb.Append( sb.Append(
$"> **`Synchronous Load (Dalamud): `** {(_tmp.Services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n"); $"> **`Synchronous Load (Dalamud): `** {(_services.GetRequiredService<DalamudServices>().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool v) ? v.ToString() : "Unknown")}\n");
sb.Append( sb.Append(
$"> **`Logging: `** Log: {_config.EnableResourceLogging}, Watcher: {_config.EnableResourceWatcher} ({_config.MaxResourceWatcherRecords})\n"); $"> **`Logging: `** Log: {_config.EnableResourceLogging}, Watcher: {_config.EnableResourceWatcher} ({_config.MaxResourceWatcherRecords})\n");
sb.Append($"> **`Use Ownership: `** {_config.UseOwnerNameForCharacterCollection}\n"); sb.Append($"> **`Use Ownership: `** {_config.UseOwnerNameForCharacterCollection}\n");

View file

@ -3,42 +3,58 @@ using Microsoft.Extensions.DependencyInjection;
using OtterGui.Classes; using OtterGui.Classes;
using OtterGui.Log; using OtterGui.Log;
using Penumbra.Api; using Penumbra.Api;
using Penumbra.Collections.Cache;
using Penumbra.Collections.Manager; using Penumbra.Collections.Manager;
using Penumbra.GameData; using Penumbra.GameData;
using Penumbra.GameData.Data; using Penumbra.GameData.Data;
using Penumbra.Interop.ResourceLoading;
using Penumbra.Interop.PathResolving; using Penumbra.Interop.PathResolving;
using Penumbra.Interop.ResourceLoading;
using Penumbra.Interop.ResourceTree; using Penumbra.Interop.ResourceTree;
using Penumbra.Interop.Services; using Penumbra.Interop.Services;
using Penumbra.Meta;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Services; using Penumbra.Mods.Manager;
using Penumbra.UI; using Penumbra.UI;
using Penumbra.UI.AdvancedWindow; using Penumbra.UI.AdvancedWindow;
using Penumbra.UI.ModsTab; using Penumbra.UI.ModsTab;
using Penumbra.UI.Tabs; using Penumbra.UI.Tabs;
using Penumbra.Util; using Penumbra.Util;
using CharacterUtility = Penumbra.Interop.Services.CharacterUtility;
using ModFileSystemSelector = Penumbra.UI.ModsTab.ModFileSystemSelector;
using Penumbra.Mods.Manager;
using Penumbra.Collections.Cache;
using Penumbra.Meta;
namespace Penumbra;
public class ServiceManager namespace Penumbra.Services;
public static class ServiceManager
{ {
public readonly ServiceProvider Services; public static ServiceProvider CreateProvider(Penumbra penumbra, DalamudPluginInterface pi, Logger log, StartTracker startTimer)
public ServiceManager(Penumbra penumbra, DalamudPluginInterface pi, Logger log)
{ {
var startTimer = new StartTracker(); var services = new ServiceCollection()
using var time = startTimer.Measure(StartTimeType.Total); .AddSingleton(log)
var services = new ServiceCollection();
// Add meta services.
services.AddSingleton(log)
.AddSingleton(startTimer) .AddSingleton(startTimer)
.AddSingleton<ValidityChecker>() .AddSingleton(penumbra)
.AddDalamud(pi)
.AddMeta()
.AddGameData()
.AddInterop()
.AddConfiguration()
.AddCollections()
.AddMods()
.AddResources()
.AddResolvers()
.AddInterface()
.AddModEditor()
.AddApi();
return services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
}
private static IServiceCollection AddDalamud(this IServiceCollection services, DalamudPluginInterface pi)
{
var dalamud = new DalamudServices(pi);
dalamud.AddServices(services);
return services;
}
private static IServiceCollection AddMeta(this IServiceCollection services)
=> services.AddSingleton<ValidityChecker>()
.AddSingleton<PerformanceTracker>() .AddSingleton<PerformanceTracker>()
.AddSingleton<FilenameService>() .AddSingleton<FilenameService>()
.AddSingleton<BackupService>() .AddSingleton<BackupService>()
@ -46,20 +62,16 @@ public class ServiceManager
.AddSingleton<ChatService>() .AddSingleton<ChatService>()
.AddSingleton<SaveService>(); .AddSingleton<SaveService>();
// Add Dalamud services
var dalamud = new DalamudServices(pi);
dalamud.AddServices(services);
services.AddSingleton(penumbra);
// Add Game Data private static IServiceCollection AddGameData(this IServiceCollection services)
services.AddSingleton<IGamePathParser, GamePathParser>() => services.AddSingleton<IGamePathParser, GamePathParser>()
.AddSingleton<IdentifierService>() .AddSingleton<IdentifierService>()
.AddSingleton<StainService>() .AddSingleton<StainService>()
.AddSingleton<ItemService>() .AddSingleton<ItemService>()
.AddSingleton<ActorService>(); .AddSingleton<ActorService>();
// Add Game Services private static IServiceCollection AddInterop(this IServiceCollection services)
services.AddSingleton<GameEventManager>() => services.AddSingleton<GameEventManager>()
.AddSingleton<FrameworkManager>() .AddSingleton<FrameworkManager>()
.AddSingleton<CutsceneService>() .AddSingleton<CutsceneService>()
.AddSingleton<CharacterUtility>() .AddSingleton<CharacterUtility>()
@ -72,12 +84,12 @@ public class ServiceManager
.AddSingleton<FontReloader>() .AddSingleton<FontReloader>()
.AddSingleton<RedrawService>(); .AddSingleton<RedrawService>();
// Add Configuration private static IServiceCollection AddConfiguration(this IServiceCollection services)
services.AddTransient<ConfigMigrationService>() => services.AddTransient<ConfigMigrationService>()
.AddSingleton<Configuration>(); .AddSingleton<Configuration>();
// Add Collection Services private static IServiceCollection AddCollections(this IServiceCollection services)
services.AddSingleton<CollectionStorage>() => services.AddSingleton<CollectionStorage>()
.AddSingleton<ActiveCollectionData>() .AddSingleton<ActiveCollectionData>()
.AddSingleton<ActiveCollections>() .AddSingleton<ActiveCollections>()
.AddSingleton<InheritanceManager>() .AddSingleton<InheritanceManager>()
@ -86,8 +98,8 @@ public class ServiceManager
.AddSingleton<CollectionEditor>() .AddSingleton<CollectionEditor>()
.AddSingleton<CollectionManager>(); .AddSingleton<CollectionManager>();
// Add Mod Services private static IServiceCollection AddMods(this IServiceCollection services)
services.AddSingleton<TempModManager>() => services.AddSingleton<TempModManager>()
.AddSingleton<ModDataEditor>() .AddSingleton<ModDataEditor>()
.AddSingleton<ModOptionEditor>() .AddSingleton<ModOptionEditor>()
.AddSingleton<ModCreator>() .AddSingleton<ModCreator>()
@ -96,16 +108,16 @@ public class ServiceManager
.AddSingleton<ModImportManager>() .AddSingleton<ModImportManager>()
.AddSingleton<ModFileSystem>() .AddSingleton<ModFileSystem>()
.AddSingleton<ModCacheManager>() .AddSingleton<ModCacheManager>()
.AddSingleton(s => (ModStorage) s.GetRequiredService<ModManager>()); .AddSingleton(s => (ModStorage)s.GetRequiredService<ModManager>());
// Add Resource services private static IServiceCollection AddResources(this IServiceCollection services)
services.AddSingleton<ResourceLoader>() => services.AddSingleton<ResourceLoader>()
.AddSingleton<ResourceWatcher>() .AddSingleton<ResourceWatcher>()
.AddSingleton<ResourceTreeFactory>() .AddSingleton<ResourceTreeFactory>()
.AddSingleton<MetaFileManager>(); .AddSingleton<MetaFileManager>();
// Add Path Resolver private static IServiceCollection AddResolvers(this IServiceCollection services)
services.AddSingleton<AnimationHookService>() => services.AddSingleton<AnimationHookService>()
.AddSingleton<CollectionResolver>() .AddSingleton<CollectionResolver>()
.AddSingleton<CutsceneService>() .AddSingleton<CutsceneService>()
.AddSingleton<DrawObjectState>() .AddSingleton<DrawObjectState>()
@ -115,8 +127,8 @@ public class ServiceManager
.AddSingleton<IdentifiedCollectionCache>() .AddSingleton<IdentifiedCollectionCache>()
.AddSingleton<PathResolver>(); .AddSingleton<PathResolver>();
// Add Interface private static IServiceCollection AddInterface(this IServiceCollection services)
services.AddSingleton<FileDialogService>() => services.AddSingleton<FileDialogService>()
.AddSingleton<TutorialService>() .AddSingleton<TutorialService>()
.AddSingleton<PenumbraChangelog>() .AddSingleton<PenumbraChangelog>()
.AddSingleton<LaunchButton>() .AddSingleton<LaunchButton>()
@ -147,8 +159,8 @@ public class ServiceManager
.AddSingleton<ResourceWatcher>() .AddSingleton<ResourceWatcher>()
.AddSingleton<ItemSwapTab>(); .AddSingleton<ItemSwapTab>();
// Add Mod Editor private static IServiceCollection AddModEditor(this IServiceCollection services)
services.AddSingleton<ModFileCollection>() => services.AddSingleton<ModFileCollection>()
.AddSingleton<DuplicateManager>() .AddSingleton<DuplicateManager>()
.AddSingleton<MdlMaterialEditor>() .AddSingleton<MdlMaterialEditor>()
.AddSingleton<ModFileEditor>() .AddSingleton<ModFileEditor>()
@ -157,17 +169,9 @@ public class ServiceManager
.AddSingleton<ModNormalizer>() .AddSingleton<ModNormalizer>()
.AddSingleton<ModEditor>(); .AddSingleton<ModEditor>();
// Add API private static IServiceCollection AddApi(this IServiceCollection services)
services.AddSingleton<PenumbraApi>() => services.AddSingleton<PenumbraApi>()
.AddSingleton<IPenumbraApi>(x => x.GetRequiredService<PenumbraApi>()) .AddSingleton<IPenumbraApi>(x => x.GetRequiredService<PenumbraApi>())
.AddSingleton<PenumbraIpcProviders>() .AddSingleton<PenumbraIpcProviders>()
.AddSingleton<HttpApi>(); .AddSingleton<HttpApi>();
Services = services.BuildServiceProvider(new ServiceProviderOptions { ValidateOnBuild = true });
}
public void Dispose()
{
Services.Dispose();
}
} }

View file

@ -1,13 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using Dalamud.Interface.Internal.Notifications; using Dalamud.Interface.Internal.Notifications;
using Dalamud.Plugin; using Dalamud.Plugin;
using Penumbra.Util;
namespace Penumbra; namespace Penumbra.Services;
public class ValidityChecker public class ValidityChecker
{ {

View file

@ -7,6 +7,7 @@ using OtterGui;
using OtterGui.Raii; using OtterGui.Raii;
using Penumbra.Api.Enums; using Penumbra.Api.Enums;
using Penumbra.Mods; using Penumbra.Mods;
using Penumbra.Services;
using Penumbra.UI.Classes; using Penumbra.UI.Classes;
using Penumbra.UI.Tabs; using Penumbra.UI.Tabs;
using Penumbra.Util; using Penumbra.Util;