Add cleanup buttons to PCP, add option to turn off PCP IPC.

This commit is contained in:
Ottermandias 2025-08-22 20:31:40 +02:00
parent 10894d451a
commit 0d64384059
2 changed files with 45 additions and 2 deletions

View file

@ -38,6 +38,7 @@ public class PcpService : IApiService, IDisposable
private readonly CommunicatorService _communicator; private readonly CommunicatorService _communicator;
private readonly SHA1 _sha1 = SHA1.Create(); private readonly SHA1 _sha1 = SHA1.Create();
private readonly ModFileSystem _fileSystem; private readonly ModFileSystem _fileSystem;
private readonly ModManager _mods;
public PcpService(Configuration config, public PcpService(Configuration config,
SaveService files, SaveService files,
@ -50,7 +51,8 @@ public class PcpService : IApiService, IDisposable
ModCreator modCreator, ModCreator modCreator,
ModExportManager modExport, ModExportManager modExport,
CommunicatorService communicator, CommunicatorService communicator,
ModFileSystem fileSystem) ModFileSystem fileSystem,
ModManager mods)
{ {
_config = config; _config = config;
_files = files; _files = files;
@ -64,10 +66,27 @@ public class PcpService : IApiService, IDisposable
_modExport = modExport; _modExport = modExport;
_communicator = communicator; _communicator = communicator;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_mods = mods;
_communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.PcpService); _communicator.ModPathChanged.Subscribe(OnModPathChange, ModPathChanged.Priority.PcpService);
} }
public void CleanPcpMods()
{
var mods = _mods.Where(m => m.ModTags.Contains("PCP")).ToList();
Penumbra.Log.Information($"[PCPService] Deleting {mods.Count} mods containing the tag PCP.");
foreach (var mod in mods)
_mods.DeleteMod(mod);
}
public void CleanPcpCollections()
{
var collections = _collections.Storage.Where(c => c.Identity.Name.StartsWith("PCP/")).ToList();
Penumbra.Log.Information($"[PCPService] Deleting {collections.Count} mods containing the tag PCP.");
foreach (var collection in collections)
_collections.Storage.Delete(collection);
}
private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, DirectoryInfo? newDirectory) private void OnModPathChange(ModPathChangeType type, Mod mod, DirectoryInfo? oldDirectory, DirectoryInfo? newDirectory)
{ {
if (type is not ModPathChangeType.Added || _config.DisablePcpHandling || newDirectory is null) if (type is not ModPathChangeType.Added || _config.DisablePcpHandling || newDirectory is null)
@ -80,12 +99,14 @@ public class PcpService : IApiService, IDisposable
{ {
// First version had collection.json, changed. // First version had collection.json, changed.
var oldFile = Path.Combine(newDirectory.FullName, "collection.json"); var oldFile = Path.Combine(newDirectory.FullName, "collection.json");
Penumbra.Log.Information("[PCPService] Renaming old PCP file from collection.json to character.json.");
if (File.Exists(oldFile)) if (File.Exists(oldFile))
File.Move(oldFile, file, true); File.Move(oldFile, file, true);
else else
return; return;
} }
Penumbra.Log.Information($"[PCPService] Found a PCP file for {mod.Name}, applying.");
var text = File.ReadAllText(file); var text = File.ReadAllText(file);
var jObj = JObject.Parse(text); var jObj = JObject.Parse(text);
var identifier = _actors.FromJson(jObj["Actor"] as JObject); var identifier = _actors.FromJson(jObj["Actor"] as JObject);
@ -116,6 +137,7 @@ public class PcpService : IApiService, IDisposable
// ignored. // ignored.
} }
} }
if (_config.AllowPcpIpc) if (_config.AllowPcpIpc)
_communicator.PcpParsing.Invoke(jObj, mod.Identifier, collection.Identity.Id); _communicator.PcpParsing.Invoke(jObj, mod.Identifier, collection.Identity.Id);
} }
@ -132,6 +154,7 @@ public class PcpService : IApiService, IDisposable
{ {
try try
{ {
Penumbra.Log.Information($"[PCPService] Creating PCP file for game object {objectIndex.Index}.");
var (identifier, tree, collection) = await _framework.Framework.RunOnFrameworkThread(() => var (identifier, tree, collection) = await _framework.Framework.RunOnFrameworkThread(() =>
{ {
var (actor, identifier) = CheckActor(objectIndex); var (actor, identifier) = CheckActor(objectIndex);
@ -178,6 +201,7 @@ public class PcpService : IApiService, IDisposable
{ {
["Version"] = 1, ["Version"] = 1,
["Actor"] = actor.ToJson(), ["Actor"] = actor.ToJson(),
["Mod"] = directory.Name,
["Collection"] = note.Length > 0 ? $"{actor.ToName()}: {note}" : actor.ToName(), ["Collection"] = note.Length > 0 ? $"{actor.ToName()}: {note}" : actor.ToName(),
["Time"] = time, ["Time"] = time,
["Note"] = note, ["Note"] = note,

View file

@ -52,6 +52,7 @@ public class SettingsTab : ITab, IUiService
private readonly CollectionAutoSelector _autoSelector; private readonly CollectionAutoSelector _autoSelector;
private readonly CleanupService _cleanupService; private readonly CleanupService _cleanupService;
private readonly AttributeHook _attributeHook; private readonly AttributeHook _attributeHook;
private readonly PcpService _pcpService;
private int _minimumX = int.MaxValue; private int _minimumX = int.MaxValue;
private int _minimumY = int.MaxValue; private int _minimumY = int.MaxValue;
@ -64,7 +65,7 @@ public class SettingsTab : ITab, IUiService
DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig, DalamudSubstitutionProvider dalamudSubstitutionProvider, FileCompactor compactor, DalamudConfigService dalamudConfig,
IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService, IDataManager gameData, PredefinedTagManager predefinedTagConfig, CrashHandlerService crashService,
MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService, MigrationSectionDrawer migrationDrawer, CollectionAutoSelector autoSelector, CleanupService cleanupService,
AttributeHook attributeHook) AttributeHook attributeHook, PcpService pcpService)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_config = config; _config = config;
@ -90,6 +91,7 @@ public class SettingsTab : ITab, IUiService
_autoSelector = autoSelector; _autoSelector = autoSelector;
_cleanupService = cleanupService; _cleanupService = cleanupService;
_attributeHook = attributeHook; _attributeHook = attributeHook;
_pcpService = pcpService;
} }
public void DrawHeader() public void DrawHeader()
@ -601,6 +603,23 @@ public class SettingsTab : ITab, IUiService
Checkbox("Handle PCP Files", Checkbox("Handle PCP Files",
"When encountering specific mods, usually but not necessarily denoted by a .pcp file ending, Penumbra will automatically try to create an associated collection and assign it to a specific character for this mod package. This can turn this behaviour off if unwanted.", "When encountering specific mods, usually but not necessarily denoted by a .pcp file ending, Penumbra will automatically try to create an associated collection and assign it to a specific character for this mod package. This can turn this behaviour off if unwanted.",
!_config.DisablePcpHandling, v => _config.DisablePcpHandling = !v); !_config.DisablePcpHandling, v => _config.DisablePcpHandling = !v);
var active = _config.DeleteModModifier.IsActive();
ImGui.SameLine();
if (ImUtf8.ButtonEx("Delete all PCP Mods"u8, "Deletes all mods tagged with 'PCP' from the mod list."u8, disabled: !active))
_pcpService.CleanPcpMods();
if (!active)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking.");
ImGui.SameLine();
if (ImUtf8.ButtonEx("Delete all PCP Collections"u8, "Deletes all collections whose name starts with 'PCP/' from the collection list."u8, disabled: !active))
_pcpService.CleanPcpCollections();
if (!active)
ImUtf8.HoverTooltip(ImGuiHoveredFlags.AllowWhenDisabled, $"Hold {_config.DeleteModModifier} while clicking.");
Checkbox("Allow Other Plugins Access to PCP Handling",
"When creating or importing PCP files, other plugins can add and interpret their own data to the character.json file.",
_config.AllowPcpIpc, v => _config.AllowPcpIpc = v);
DrawDefaultModImportPath(); DrawDefaultModImportPath();
DrawDefaultModAuthor(); DrawDefaultModAuthor();
DrawDefaultModImportFolder(); DrawDefaultModImportFolder();