-
Notifications
You must be signed in to change notification settings - Fork 0
/
PenumbraIpc.cs
303 lines (246 loc) · 10.7 KB
/
PenumbraIpc.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
using System.Diagnostics.CodeAnalysis;
using Heliosphere.Ui;
using JetBrains.Annotations;
using Penumbra.Api.Enums;
using Penumbra.Api.Helpers;
using Penumbra.Api.IpcSubscribers;
namespace Heliosphere;
internal class PenumbraIpc : IDisposable {
private Plugin Plugin { get; }
private PenumbraWindowIntegration WindowIntegration { get; }
/// <inheritdoc cref="ApiVersion" />
private ApiVersion ApiVersionSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetModDirectory" />
private GetModDirectory GetModDirectorySubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.AddMod" />
private AddMod AddModSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.ReloadMod" />
private ReloadMod ReloadModSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.SetModPath" />
private SetModPath SetModPathSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.DeleteMod" />
private DeleteMod DeleteModSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.CopyModSettings" />
private CopyModSettings CopyModSettingsSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetCollections" />
private GetCollections GetCollectionsSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.TrySetMod" />
private TrySetMod TrySetModSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetModPath" />
private GetModPath GetModPathSubscriber { get; }
/// <inheritdoc cref="OpenMainWindow" />
private OpenMainWindow OpenMainWindowSubscriber { get; }
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetCurrentModSettings" />
private GetCurrentModSettings GetCurrentModSettingsSubscriber { get; set; }
/// <inheritdoc cref="GetModList" />
private GetModList GetModListSubscriber { get; }
// events
/// <inheritdoc cref="Initialized" />
private EventSubscriber InitializedEvent { get; set; }
/// <inheritdoc cref="ModAdded" />
private EventSubscriber<string>? ModAddedEvent { get; set; }
/// <inheritdoc cref="ModDeleted" />
private EventSubscriber<string>? ModDeletedEvent { get; set; }
/// <inheritdoc cref="ModMoved" />
private EventSubscriber<string, string>? ModMovedEvent { get; set; }
/// <inheritdoc cref="PostEnabledDraw" />
private EventSubscriber<string>? PostEnabledDrawEvent { get; set; }
/// <inheritdoc cref="PreSettingsTabBarDraw" />
private EventSubscriber<string, float, float>? PreSettingsTabBarDrawEvent { get; set; }
internal PenumbraIpc(Plugin plugin) {
this.Plugin = plugin;
this.WindowIntegration = new PenumbraWindowIntegration(this.Plugin);
this.ApiVersionSubscriber = new ApiVersion(this.Plugin.Interface);
this.GetModDirectorySubscriber = new GetModDirectory(this.Plugin.Interface);
this.AddModSubscriber = new AddMod(this.Plugin.Interface);
this.ReloadModSubscriber = new ReloadMod(this.Plugin.Interface);
this.SetModPathSubscriber = new SetModPath(this.Plugin.Interface);
this.DeleteModSubscriber = new DeleteMod(this.Plugin.Interface);
this.CopyModSettingsSubscriber = new CopyModSettings(this.Plugin.Interface);
this.GetCollectionsSubscriber = new GetCollections(this.Plugin.Interface);
this.TrySetModSubscriber = new TrySetMod(this.Plugin.Interface);
this.GetModPathSubscriber = new GetModPath(this.Plugin.Interface);
this.OpenMainWindowSubscriber = new OpenMainWindow(this.Plugin.Interface);
this.GetCurrentModSettingsSubscriber = new GetCurrentModSettings(this.Plugin.Interface);
this.GetModListSubscriber = new GetModList(this.Plugin.Interface);
this.RegisterEvents();
}
public void Dispose() {
this.UnregisterEvents();
}
private void ReregisterEvents() {
this.UnregisterEvents();
this.RegisterEvents();
}
private void UnregisterEvents() {
this.PreSettingsTabBarDrawEvent?.Dispose();
this.PostEnabledDrawEvent?.Dispose();
this.ModMovedEvent?.Dispose();
this.ModDeletedEvent?.Dispose();
this.ModAddedEvent?.Dispose();
this.InitializedEvent?.Dispose();
}
private void RegisterEvents() {
this.InitializedEvent = Initialized.Subscriber(this.Plugin.Interface, this.ReregisterEvents);
this.ModAddedEvent = ModAdded.Subscriber(this.Plugin.Interface, _ => {
Task.Run(async () => await this.Plugin.State.UpdatePackages());
});
this.ModDeletedEvent = ModDeleted.Subscriber(this.Plugin.Interface, _ => {
Task.Run(async () => await this.Plugin.State.UpdatePackages());
});
this.ModMovedEvent = ModMoved.Subscriber(this.Plugin.Interface, (_, _) => {
Task.Run(async () => await this.Plugin.State.UpdatePackages());
});
this.PostEnabledDrawEvent = PostEnabledDraw.Subscriber(this.Plugin.Interface, this.WindowIntegration.PostEnabledDraw);
this.PreSettingsTabBarDrawEvent = PreSettingsTabBarDraw.Subscriber(this.Plugin.Interface, this.WindowIntegration.PreSettingsTabBarDraw);
}
internal bool AtLeastVersion((int breaking, int features) tuple) {
return this.AtLeastVersion(tuple.breaking, tuple.features);
}
internal bool AtLeastVersion(int breaking, int features) {
if (this.GetApiVersions() is not var (installedBreaking, installedFeatures)) {
return false;
}
if (installedBreaking > breaking) {
return true;
}
return installedBreaking == breaking && installedFeatures >= features;
}
private (int Breaking, int Features)? GetApiVersions() {
try {
return this.ApiVersionSubscriber.Invoke();
} catch (Exception) {
return null;
}
}
internal string? GetModDirectory() {
try {
return this.GetModDirectorySubscriber.Invoke();
} catch (Exception) {
return null;
}
}
/// <summary>
/// Gets the mod directory from Penumbra. Will open a warning popup to users
/// who have not set Penumbra up correctly.
/// </summary>
/// <param name="modDirectory">The mod directory</param>
/// <returns>true if the mod directory is valid, false if invalid or Penumbra's IPC could not be contacted</returns>
internal bool TryGetModDirectory([NotNullWhen(true)] out string? modDirectory) {
modDirectory = this.GetModDirectory();
if (modDirectory?.Trim() == string.Empty) {
Task.Run(async () => await this.Plugin.PluginUi.AddIfNotPresentAsync(new SetUpPenumbraWindow(this.Plugin)));
}
return !string.IsNullOrWhiteSpace(modDirectory);
}
[MustUseReturnValue]
internal PenumbraApiEc? AddMod(string path) {
try {
return this.AddModSubscriber.Invoke(path);
} catch (Exception) {
return null;
}
}
internal bool ReloadMod(string directoryName) {
try {
return this.ReloadModSubscriber.Invoke(directoryName) == PenumbraApiEc.Success;
} catch (Exception) {
return false;
}
}
internal bool SetModPath(string directoryName, string newPath) {
try {
return this.SetModPathSubscriber.Invoke(directoryName, newPath) == PenumbraApiEc.Success;
} catch (Exception) {
return false;
}
}
internal bool DeleteMod(string directoryName) {
try {
return this.DeleteModSubscriber.Invoke(directoryName) == PenumbraApiEc.Success;
} catch (Exception) {
return false;
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.CopyModSettings"/>
internal bool CopyModSettings(string from, string to) {
try {
return this.CopyModSettingsSubscriber.Invoke(null, from, to) == PenumbraApiEc.Success;
} catch (Exception) {
return false;
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetCollections"/>
internal IReadOnlyDictionary<Guid, string>? GetCollections() {
try {
return this.GetCollectionsSubscriber.Invoke();
} catch (Exception) {
return null;
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.TrySetMod"/>
internal bool TrySetMod(Guid collectionId, string directory, bool enabled) {
try {
return this.TrySetModSubscriber.Invoke(collectionId, directory, enabled) == PenumbraApiEc.Success;
} catch (Exception) {
return false;
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetModPath"/>
internal string? GetModPath(string directoryName) {
try {
var (status, path, _, _) = this.GetModPathSubscriber.Invoke(directoryName);
return status == PenumbraApiEc.Success ? path : null;
} catch (Exception) {
return null;
}
}
internal void OpenMod(string modDirectory) {
try {
this.OpenMainWindowSubscriber.Invoke(TabType.Mods, modDirectory);
} catch (Exception) {
// no-op
}
}
internal void OpenSettings() {
try {
this.OpenMainWindowSubscriber.Invoke(TabType.Settings);
} catch (Exception) {
// no-op
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetCurrentModSettings"/>
internal (PenumbraApiEc, CurrentModSettings?)? GetCurrentModSettings(Guid collectionId, string modDirectory, bool ignoreInheritance) {
try {
var (ec, tuple) = this.GetCurrentModSettingsSubscriber.Invoke(collectionId, modDirectory, "", ignoreInheritance);
if (tuple == null) {
return (ec, null);
}
return (ec, new CurrentModSettings {
Enabled = tuple.Value.Item1,
Priority = tuple.Value.Item2,
EnabledOptions = tuple.Value.Item3,
Inherited = tuple.Value.Item4,
});
} catch (Exception) {
return null;
}
}
/// <inheritdoc cref="Penumbra.Api.IpcSubscribers.GetModList"/>
internal IDictionary<string, string>? GetMods() {
try {
return this.GetModListSubscriber.Invoke();
} catch (Exception) {
return null;
}
}
}
internal struct CurrentModSettings {
internal required bool Enabled { get; init; }
internal required int Priority { get; init; }
/// <summary>
/// A dictionary of option group names and lists of enabled option names.
/// </summary>
internal required Dictionary<string, List<string>> EnabledOptions { get; init; }
internal required bool Inherited { get; init; }
}