Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Penumbra.ReloadMod API doesn't function properly. #402

Open
Sevii77 opened this issue Mar 16, 2024 · 5 comments
Open

Penumbra.ReloadMod API doesn't function properly. #402

Sevii77 opened this issue Mar 16, 2024 · 5 comments

Comments

@Sevii77
Copy link

Sevii77 commented Mar 16, 2024

Creating a new option group and calling Penumbra.ReloadMod will not properly reload the mod. The following code creates a new mod, adds a new group, update it, and tries to update the setting of it:

var root = $"{Interface.GetIpcSubscriber<string>("Penumbra.GetModDirectory").InvokeFunc()}/IssueExample";
Directory.CreateDirectory(root);
File.WriteAllText($"{root}/meta.json", """{"FileVersion":3,"Name":"IssueExample","Author":"","Description":"","Version":"1.0.0","Website": "","ModTags": []}""");
File.WriteAllText($"{root}/default_mod.json", """{"Name":"","Description":"","Files":{},"FileSwaps":{},"Manipulations":[]}""");
Interface.GetIpcSubscriber<string, byte>("Penumbra.AddMod").InvokeFunc("IssueExample");

var option = """{"Name": "option","Description":"","Priority":1,"Type":"Single","DefaultSettings":0,"Options":["""; // ]}
var sub_option1 = """{"Name":"1","Description":"","Files":{},"FileSwaps":{},"Manipulations":[]}""";
var sub_option2 = """{"Name":"2","Description":"","Files":{},"FileSwaps":{},"Manipulations":[]}""";

File.WriteAllText($"{root}/group_001_option.json", option + sub_option1 + "]}");
Interface.GetIpcSubscriber<string, string, byte>("Penumbra.ReloadMod").InvokeFunc("IssueExample", "");
// Interface.GetIpcSubscriber<string, string, string, string, string, byte>("Penumbra.TrySetModSetting").InvokeFunc("Default", "IssueExample", "", "option", "1");

File.WriteAllText($"{root}/group_001_option.json", option + sub_option1 + "," + sub_option2 + "]}");
Interface.GetIpcSubscriber<string, string, byte>("Penumbra.ReloadMod").InvokeFunc("IssueExample", "");

try {
	Interface.GetIpcSubscriber<string, string, string, string, string, byte>("Penumbra.TrySetModSetting").InvokeFunc("Default", "IssueExample", "", "option", "1");
} catch(Exception e) {
	Logger.Error(e, "");
}

Creating and updating the group causes the settings ui to error:

Exception thrown during ModPanel Render
System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
   at Penumbra.UI.ModsTab.ModPanelSettingsTab.DrawSingleGroupRadio(IModGroup group, Int32 groupIdx)
   at Penumbra.UI.ModsTab.ModPanelSettingsTab.DrawContent() in D:\a\Penumbra\Penumbra\Penumbra\UI\ModsTab\ModPanelSettingsTab.cs:line 94
   at OtterGui.Widgets.TabBar.Draw(String label, ImGuiTabBarFlags flags, ReadOnlySpan`1 selectTab, ReadOnlySpan`1& currentTab, Action buttons, ITab[] tabs) in D:\a\Penumbra\Penumbra\OtterGui\Widgets\TabBar.cs:line 54
   at Penumbra.UI.ModsTab.ModPanelTabBar.Draw(Mod mod) in D:\a\Penumbra\Penumbra\Penumbra\UI\ModsTab\ModPanelTabBar.cs:line 74
   at Penumbra.UI.ModsTab.ModPanel.Draw() in D:\a\Penumbra\Penumbra\Penumbra\UI\ModsTab\ModPanel.cs:line 49
   at Penumbra.UI.Tabs.ModsTab.DrawContent() in D:\a\Penumbra\Penumbra\Penumbra\UI\Tabs\ModsTab.cs:line 81

And setting the settings will cause that to throw an exception, this also happens if the group is only created once, and ReloadMod called once

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
   at Penumbra.Collections.Manager.CollectionEditor.SetModSetting(ModCollection collection, Mod mod, Int32 groupIdx, UInt32 newValue) in D:\a\Penumbra\Penumbra\Penumbra\Collections\Manager\CollectionEditor.cs:line 104
   at Penumbra.Api.PenumbraApi.TrySetModSetting(String collectionName, String modDirectory, String modName, String optionGroupName, String optionName) in D:\a\Penumbra\Penumbra\Penumbra\Api\PenumbraApi.cs:line 802
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)

This code also causes my game to crash sometimes but I can't get that to be consistent.

@Ottermandias
Copy link
Collaborator

Works fine for me. Are you doing this off mainthread?

@Ottermandias
Copy link
Collaborator

image

@Ottermandias
Copy link
Collaborator

image

@Sevii77
Copy link
Author

Sevii77 commented Mar 17, 2024

My actual use case is on a separate thread and the test was done in a plugin ctor (which I assume is either a thread or async task), the issue persists even when called from a draw event as in your code. I've uploaded the plugin I used to test this: https://github.com/Sevii77/penumbra_issue

On a side note, my current workaround is to delete and add the mod back, which works even on a separate thread.

var root = $"{Interface.GetIpcSubscriber<string>("Penumbra.GetModDirectory").InvokeFunc()}/{id}";
Directory.Move(root, $"{root}_TEMP");
Interface.GetIpcSubscriber<string, string, byte>("Penumbra.DeleteMod").InvokeFunc(id, "");
Directory.Move($"{root}_TEMP", root);
return Interface.GetIpcSubscriber<string, byte>("Penumbra.AddMod").InvokeFunc(id);

@Ottermandias
Copy link
Collaborator

Reloading an existing mod doesn't seem to generate default settings or fix invalid settings (not just via IPC). Probably fixed it for next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants