using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.NET.Common;
using BepInExResoniteShim;
using Elements.Core;
using FrooxEngine;
using FrooxEngine.UIX;
using HarmonyLib;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]
[assembly: AssemblyMetadata("ResoniteSdkVersion", "2.3.4")]
[assembly: AssemblyMetadata("ResoniteVersion", "2026.8.27.1094")]
[assembly: IgnoresAccessChecksTo("FrooxEngine")]
[assembly: IgnoresAccessChecksTo("Elements.Core")]
[assembly: IgnoresAccessChecksTo("Elements.Assets")]
[assembly: AssemblyCompany("blhsrwznrghfzpr")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Adds a button to save Resonite settings without exiting the game.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SettingsSaveNow")]
[assembly: AssemblyTitle("SettingsSaveNow")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/blhsrwznrghfzpr/SettingsSaveNow")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace SettingsSaveNow;
[ResonitePlugin("dev.blhsrwznrghfzpr.SettingsSaveNow", "SettingsSaveNow", "1.0.0", "blhsrwznrghfzpr", "https://github.com/blhsrwznrghfzpr/SettingsSaveNow")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BasePlugin
{
public const string PluginGuid = "dev.blhsrwznrghfzpr.SettingsSaveNow";
public override void Load()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Expected O, but got Unknown
Harmony val = new Harmony("dev.blhsrwznrghfzpr.SettingsSaveNow");
try
{
val.PatchAll(typeof(Plugin).Assembly);
}
catch
{
val.UnpatchSelf();
throw;
}
((BasePlugin)this).Log.LogInfo((object)"SettingsSaveNow loaded.");
}
}
internal static class SaveButton
{
private enum SaveStatus
{
Ready,
Saving,
Completed,
Failed,
Disabled,
NotReady
}
[CompilerGenerated]
private static class <>O
{
public static ButtonEventHandler <0>__OnPressed;
}
[CompilerGenerated]
private sealed class <>c__DisplayClass6_0
{
[StructLayout((LayoutKind)3)]
private struct <<OnPressed>b__0>d : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
public <>c__DisplayClass6_0 <>4__this;
private object <>7__wrap1;
private int <>7__wrap2;
private TaskAwaiter<bool> <>u__1;
private ToWorld <>u__2;
private void MoveNext()
{
//IL_0115: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
<>c__DisplayClass6_0 CS$<>8__locals1 = <>4__this;
try
{
ToWorld val;
if (num != 0)
{
if (num == 1)
{
val = <>u__2;
<>u__2 = default(ToWorld);
num = (<>1__state = -1);
goto IL_0169;
}
<>7__wrap2 = 0;
}
try
{
TaskAwaiter<bool> val2;
if (num != 0)
{
val2 = Operation.TryRunAsync([AsyncStateMachine(typeof(<<OnPressed>b__1>d))] () =>
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<<OnPressed>b__1>d <<OnPressed>b__1>d = default(<<OnPressed>b__1>d);
<<OnPressed>b__1>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<OnPressed>b__1>d.<>4__this = CS$<>8__locals1;
<<OnPressed>b__1>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<OnPressed>b__1>d.<>t__builder)).Start<<<OnPressed>b__1>d>(ref <<OnPressed>b__1>d);
return ((AsyncTaskMethodBuilder)(ref <<OnPressed>b__1>d.<>t__builder)).Task;
}).GetAwaiter();
if (!val2.IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = val2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<TaskAwaiter<bool>, <<OnPressed>b__0>d>(ref val2, ref this);
return;
}
}
else
{
val2 = <>u__1;
<>u__1 = default(TaskAwaiter<bool>);
num = (<>1__state = -1);
}
if (val2.GetResult())
{
UpdateButtons(SaveStatus.Completed);
UniLog.Log("[SettingsSaveNow] Settings save completed; cloud synchronization is handled by Resonite.", false);
}
}
catch (global::System.Exception ex)
{
<>7__wrap1 = ex;
<>7__wrap2 = 1;
}
int num2 = <>7__wrap2;
if (num2 == 1)
{
global::System.Exception ex2 = (global::System.Exception)<>7__wrap1;
UniLog.Error($"[SettingsSaveNow] Settings save failed:\n{ex2}", true);
ToWorld val3 = default(ToWorld);
val = ((ToWorld)(ref val3)).GetAwaiter();
if (!((ToWorld)(ref val)).IsCompleted)
{
num = (<>1__state = 1);
<>u__2 = val;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompleted<ToWorld, <<OnPressed>b__0>d>(ref val, ref this);
return;
}
goto IL_0169;
}
goto IL_0176;
IL_0169:
((ToWorld)(ref val)).GetResult();
UpdateButtons(SaveStatus.Failed);
goto IL_0176;
IL_0176:
<>7__wrap1 = null;
}
catch (global::System.Exception exception)
{
<>1__state = -2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
return;
}
<>1__state = -2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
}
}
[StructLayout((LayoutKind)3)]
private struct <<OnPressed>b__1>d : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
public <>c__DisplayClass6_0 <>4__this;
private Updates <>u__1;
private TaskAwaiter <>u__2;
private ToWorld <>u__3;
private void MoveNext()
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
<>c__DisplayClass6_0 <>c__DisplayClass6_ = <>4__this;
try
{
Updates val3;
TaskAwaiter val2;
ToWorld val;
ToWorld val5;
switch (num)
{
default:
{
UpdateButtons(SaveStatus.Saving);
Updates val4 = new Updates(1);
val3 = ((Updates)(ref val4)).GetAwaiter();
if (!((Updates)(ref val3)).IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = val3;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompleted<Updates, <<OnPressed>b__1>d>(ref val3, ref this);
return;
}
goto IL_007d;
}
case 0:
val3 = <>u__1;
<>u__1 = default(Updates);
num = (<>1__state = -1);
goto IL_007d;
case 1:
val2 = <>u__2;
<>u__2 = default(TaskAwaiter);
num = (<>1__state = -1);
goto IL_00e0;
case 2:
{
val = <>u__3;
<>u__3 = default(ToWorld);
num = (<>1__state = -1);
break;
}
IL_00e0:
((TaskAwaiter)(ref val2)).GetResult();
val5 = default(ToWorld);
val = ((ToWorld)(ref val5)).GetAwaiter();
if (!((ToWorld)(ref val)).IsCompleted)
{
num = (<>1__state = 2);
<>u__3 = val;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitOnCompleted<ToWorld, <<OnPressed>b__1>d>(ref val, ref this);
return;
}
break;
IL_007d:
((Updates)(ref val3)).GetResult();
val2 = <>c__DisplayClass6_.manager.SaveAllSettings().GetAwaiter();
if (!((TaskAwaiter)(ref val2)).IsCompleted)
{
num = (<>1__state = 1);
<>u__2 = val2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<TaskAwaiter, <<OnPressed>b__1>d>(ref val2, ref this);
return;
}
goto IL_00e0;
}
((ToWorld)(ref val)).GetResult();
}
catch (global::System.Exception exception)
{
<>1__state = -2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
return;
}
<>1__state = -2;
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetResult();
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
((AsyncTaskMethodBuilder)(ref <>t__builder)).SetStateMachine(stateMachine);
}
}
public SettingManagersManager manager;
public Func<global::System.Threading.Tasks.Task> <>9__1;
[AsyncStateMachine(typeof(<<OnPressed>b__0>d))]
internal global::System.Threading.Tasks.Task <OnPressed>b__0()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<<OnPressed>b__0>d <<OnPressed>b__0>d = default(<<OnPressed>b__0>d);
<<OnPressed>b__0>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<OnPressed>b__0>d.<>4__this = this;
<<OnPressed>b__0>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<OnPressed>b__0>d.<>t__builder)).Start<<<OnPressed>b__0>d>(ref <<OnPressed>b__0>d);
return ((AsyncTaskMethodBuilder)(ref <<OnPressed>b__0>d.<>t__builder)).Task;
}
[AsyncStateMachine(typeof(<<OnPressed>b__1>d))]
internal global::System.Threading.Tasks.Task <OnPressed>b__1()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<<OnPressed>b__1>d <<OnPressed>b__1>d = default(<<OnPressed>b__1>d);
<<OnPressed>b__1>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<OnPressed>b__1>d.<>4__this = this;
<<OnPressed>b__1>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<OnPressed>b__1>d.<>t__builder)).Start<<<OnPressed>b__1>d>(ref <<OnPressed>b__1>d);
return ((AsyncTaskMethodBuilder)(ref <<OnPressed>b__1>d.<>t__builder)).Task;
}
}
private const string SlotName = "SettingsSaveNow.SaveButton";
private static readonly SaveOperation Operation = new SaveOperation();
private static readonly List<WeakReference<Button>> Buttons = new List<WeakReference<Button>>();
private static SaveStatus _status;
internal static void Attach(RootCategoryView view)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Expected O, but got Unknown
Slot target = view.CategoryManager.ContainerRoot.Target;
if (target != null && target.FindChild("SettingsSaveNow.SaveButton") == null)
{
UIBuilder val = new UIBuilder(target, (Slot)null);
RadiantUI_Constants.SetupBaseStyle(val);
LocaleString val2 = LocaleString.op_Implicit(Label(_status));
Button val3 = val.Button(ref val2);
((Component)val3).Slot.Name = "SettingsSaveNow.SaveButton";
((Component)val3).Slot.PersistentSelf = false;
((Component)val3).Slot.OrderOffset = -9223372036854775808L;
((SyncField<float>)(object)(((ContainerWorker<Component>)(object)((Component)val3).Slot).GetComponent<LayoutElement>((Predicate<LayoutElement>)null, false) ?? ((ContainerWorker<Component>)(object)((Component)val3).Slot).AttachComponent<LayoutElement>(true, (Action<LayoutElement>)null)).MinHeight).Value = 40f;
object obj = <>O.<0>__OnPressed;
if (obj == null)
{
ButtonEventHandler val4 = OnPressed;
<>O.<0>__OnPressed = val4;
obj = (object)val4;
}
val3.LocalPressed += (ButtonEventHandler)obj;
Buttons.Add(new WeakReference<Button>(val3));
UpdateButtons(_status);
}
}
private static void OnPressed(IButton button, ButtonEventData eventData)
{
<>c__DisplayClass6_0 CS$<>8__locals5 = new <>c__DisplayClass6_0();
if (Operation.IsRunning)
{
return;
}
World world = ((IWorldElement)button).World;
if (!WorldExtensions.IsUserspace(world))
{
return;
}
CS$<>8__locals5.manager = world.GetGloballyRegisteredComponent<SettingManagersManager>((Predicate<SettingManagersManager>)null);
if (CS$<>8__locals5.manager == null || CS$<>8__locals5.manager.LocalSettings.Target == null)
{
UpdateButtons(SaveStatus.NotReady);
return;
}
if (SettingManagersManager.NeverSave)
{
UpdateButtons(SaveStatus.Disabled);
return;
}
((Worker)CS$<>8__locals5.manager).StartTask((Func<global::System.Threading.Tasks.Task>)([AsyncStateMachine(typeof(<>c__DisplayClass6_0.<<OnPressed>b__0>d))] () =>
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
<>c__DisplayClass6_0.<<OnPressed>b__0>d <<OnPressed>b__0>d = default(<>c__DisplayClass6_0.<<OnPressed>b__0>d);
<<OnPressed>b__0>d.<>t__builder = AsyncTaskMethodBuilder.Create();
<<OnPressed>b__0>d.<>4__this = CS$<>8__locals5;
<<OnPressed>b__0>d.<>1__state = -1;
((AsyncTaskMethodBuilder)(ref <<OnPressed>b__0>d.<>t__builder)).Start<<>c__DisplayClass6_0.<<OnPressed>b__0>d>(ref <<OnPressed>b__0>d);
return ((AsyncTaskMethodBuilder)(ref <<OnPressed>b__0>d.<>t__builder)).Task;
}));
}
private static void UpdateButtons(SaveStatus status)
{
_status = status;
Button val = default(Button);
for (int num = Buttons.Count - 1; num >= 0; num--)
{
if (!Buttons[num].TryGetTarget(ref val) || ((Worker)val).IsRemoved)
{
Buttons.RemoveAt(num);
}
else
{
((ComponentBase<Component>)(object)val).Enabled = status != SaveStatus.Saving;
Text componentInChildren = ((Component)val).Slot.GetComponentInChildren<Text>((Predicate<Text>)null, false, false);
if (componentInChildren != null)
{
((SyncField<string>)(object)componentInChildren.Content).Value = Label(status);
}
}
}
}
private static string Label(SaveStatus status)
{
LocaleSettings activeSetting = Settings.GetActiveSetting<LocaleSettings>();
bool flag = (((activeSetting != null) ? activeSetting.ActiveLocaleCode : null) ?? LocaleSettings.SystemLocale)?.StartsWith("ja", (StringComparison)5) ?? false;
switch (status)
{
case SaveStatus.Saving:
if (flag)
{
return "保存中…";
}
return "Saving...";
case SaveStatus.Completed:
if (flag)
{
return "保存完了(再保存)";
}
return "Saved (save again)";
case SaveStatus.Failed:
if (flag)
{
return "保存失敗(再試行)";
}
return "Failed (retry)";
case SaveStatus.Disabled:
if (flag)
{
return "保存は無効です";
}
return "Saving disabled";
case SaveStatus.NotReady:
if (flag)
{
return "設定の読込待ち";
}
return "Settings not ready";
default:
if (flag)
{
return "保存";
}
return "Save settings";
}
}
}
internal sealed class SaveOperation
{
[StructLayout((LayoutKind)3)]
[CompilerGenerated]
private struct <TryRunAsync>d__3 : IAsyncStateMachine
{
public int <>1__state;
public AsyncTaskMethodBuilder<bool> <>t__builder;
public SaveOperation <>4__this;
public Func<global::System.Threading.Tasks.Task> save;
private TaskAwaiter <>u__1;
private void MoveNext()
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
int num = <>1__state;
SaveOperation saveOperation = <>4__this;
bool result;
try
{
if (num != 0 && Interlocked.CompareExchange(ref saveOperation._running, 1, 0) != 0)
{
result = false;
}
else
{
try
{
TaskAwaiter val;
if (num != 0)
{
val = save.Invoke().GetAwaiter();
if (!((TaskAwaiter)(ref val)).IsCompleted)
{
num = (<>1__state = 0);
<>u__1 = val;
<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, <TryRunAsync>d__3>(ref val, ref this);
return;
}
}
else
{
val = <>u__1;
<>u__1 = default(TaskAwaiter);
num = (<>1__state = -1);
}
((TaskAwaiter)(ref val)).GetResult();
result = true;
}
finally
{
if (num < 0)
{
Volatile.Write(ref saveOperation._running, 0);
}
}
}
}
catch (global::System.Exception exception)
{
<>1__state = -2;
<>t__builder.SetException(exception);
return;
}
<>1__state = -2;
<>t__builder.SetResult(result);
}
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
<>t__builder.SetStateMachine(stateMachine);
}
}
private int _running;
public bool IsRunning => Volatile.Read(ref _running) != 0;
[AsyncStateMachine(typeof(<TryRunAsync>d__3))]
public async global::System.Threading.Tasks.Task<bool> TryRunAsync(Func<global::System.Threading.Tasks.Task> save)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
if (Interlocked.CompareExchange(ref _running, 1, 0) != 0)
{
return false;
}
try
{
await save.Invoke();
return true;
}
finally
{
Volatile.Write(ref _running, 0);
}
}
}
[HarmonyPatch(typeof(RootCategoryView), "OnFeedGenerationFinished")]
internal static class SettingsViewPatch
{
[HarmonyPostfix]
private static void Postfix(RootCategoryView __instance)
{
if (!(((DataFeedViewBase)__instance).Feed.Target is SettingsDataFeed) || !WorldExtensions.IsUserspace(((Worker)__instance).World))
{
return;
}
try
{
SaveButton.Attach(__instance);
}
catch (global::System.Exception ex)
{
UniLog.Error($"[SettingsSaveNow] Could not add the save button:\n{ex}", true);
}
}
}
public static class PluginMetadata
{
public const string GUID = "SettingsSaveNow";
public const string NAME = "SettingsSaveNow";
public const string VERSION = "1.0.0";
public const string AUTHORS = "blhsrwznrghfzpr";
public const string REPOSITORY_URL = "https://github.com/blhsrwznrghfzpr/SettingsSaveNow";
}