using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("AuroraQuickConnect")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AuroraQuickConnect")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b320a5f6-47c1-4fb0-a279-c04835cbb413")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
}
namespace AuroraQuickConnect
{
[BepInPlugin("com.aurora.quickconnect", "AuroraQuickConnect", "1.0.0")]
public sealed class Class1 : BaseUnityPlugin
{
private static class Joiner
{
public static bool TryJoin(FejdStartup fs, string host, int port, string password)
{
string text = $"{host}:{port}";
Ui.TryFillJoinByIp(fs, text, password);
if (SmartInvoke.TryInvokeFirstMatch(fs, new string[8] { "OnJoinIPConnect", "OnJoinIpConnect", "JoinServerIP", "JoinServerIp", "JoinServer", "ConnectToServer", "ConnectToIP", "ConnectToIp" }, SmartInvoke.Candidates(new object[0], new object[1] { text }, new object[2] { text, password }, new object[2] { host, port }, new object[3] { host, port, password })))
{
return true;
}
if (TryJoinViaMatchmaking(text))
{
return true;
}
if (TryJoinViaZNet(host, port, text))
{
return true;
}
return false;
}
private static bool TryJoinViaMatchmaking(string hostAndPort)
{
try
{
Type type = AccessTools.TypeByName("ZSteamMatchmaking");
if (type == null)
{
return false;
}
object obj = AccessTools.Property(type, "instance")?.GetValue(null) ?? AccessTools.Field(type, "instance")?.GetValue(null);
if (obj == null)
{
return false;
}
if (SmartInvoke.TryInvokeFirstMatch(obj, new string[6] { "QueueServerJoin", "JoinServer", "JoinServerByIp", "JoinServerByIP", "JoinIP", "JoinIp" }, SmartInvoke.Candidates(new object[1] { hostAndPort })))
{
Log.LogInfo((object)"Aurora QuickConnect: join triggered via ZSteamMatchmaking.");
return true;
}
}
catch (Exception ex)
{
Log.LogDebug((object)("TryJoinViaMatchmaking failed: " + ex.GetType().Name + ": " + ex.Message));
}
return false;
}
private static bool TryJoinViaZNet(string host, int port, string hostAndPort)
{
try
{
Type type = AccessTools.TypeByName("ZNet");
if (type == null)
{
return false;
}
object obj = AccessTools.Property(type, "instance")?.GetValue(null) ?? AccessTools.Field(type, "instance")?.GetValue(null);
if (obj == null)
{
return false;
}
IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(host), port);
if (SmartInvoke.TryInvokeFirstMatch(obj, new string[6] { "Connect", "StartClient", "StartClientConnect", "ConnectToServer", "ConnectToIP", "ConnectToIp" }, SmartInvoke.Candidates(new object[2] { host, port }, new object[1] { hostAndPort }, new object[1] { iPEndPoint })))
{
Log.LogInfo((object)"Aurora QuickConnect: join triggered via ZNet.");
return true;
}
}
catch (Exception ex)
{
Log.LogDebug((object)("TryJoinViaZNet failed: " + ex.GetType().Name + ": " + ex.Message));
}
return false;
}
public static void DumpJoinMethods(FejdStartup fs)
{
try
{
DumpTypeMethods("FejdStartup", ((object)fs).GetType(), "join");
DumpTypeMethods("FejdStartup", ((object)fs).GetType(), "connect");
Type type = AccessTools.TypeByName("ZSteamMatchmaking");
if (type != null)
{
DumpTypeMethods("ZSteamMatchmaking", type, "join");
}
Type type2 = AccessTools.TypeByName("ZNet");
if (type2 != null)
{
DumpTypeMethods("ZNet", type2, "connect");
}
}
catch (Exception ex)
{
Log.LogWarning((object)("DumpJoinMethods failed: " + ex.GetType().Name + ": " + ex.Message));
}
}
private static void DumpTypeMethods(string label, Type t, string filter)
{
string filter2 = filter;
string[] array = (from m in (from m in t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where m.Name.IndexOf(filter2, StringComparison.OrdinalIgnoreCase) >= 0
orderby m.Name
select m).Take(60)
select m.Name + "(" + string.Join(", ", from p in m.GetParameters()
select p.ParameterType.Name) + ")").ToArray();
Log.LogInfo((object)("---- " + label + " methods matching '" + filter2 + "' (up to 60) ----"));
string[] array2 = array;
foreach (string text in array2)
{
Log.LogInfo((object)text);
}
Log.LogInfo((object)"--------------------------------------------------------");
}
}
private static class SmartInvoke
{
public static object[][] Candidates(params object[][] candidates)
{
return candidates;
}
public static bool TryInvokeFirstMatch(object instance, string[] methodNames, object[][] candidates)
{
Type type = instance.GetType();
MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (string name in methodNames)
{
foreach (MethodInfo item in methods.Where((MethodInfo x) => x.Name == name))
{
foreach (object[] candidate in candidates)
{
if (!TryBuildArgs(item, candidate, out object[] args))
{
continue;
}
try
{
item.Invoke(instance, args);
Log.LogInfo((object)("Invoked " + type.Name + "." + item.Name + "(" + string.Join(", ", from p in item.GetParameters()
select p.ParameterType.Name) + ")"));
return true;
}
catch (Exception ex)
{
Log.LogDebug((object)("Invoke failed " + type.Name + "." + item.Name + ": " + ex.GetType().Name + ": " + ex.Message));
}
}
}
}
return false;
}
private static bool TryBuildArgs(MethodInfo method, object[] candidate, out object[] args)
{
args = Array.Empty<object>();
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length != candidate.Length)
{
return false;
}
object[] array = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
Type parameterType = parameters[i].ParameterType;
object obj = candidate[i];
if (obj == null)
{
if (parameterType.IsValueType)
{
return false;
}
array[i] = null;
continue;
}
Type type = obj.GetType();
if (parameterType.IsAssignableFrom(type))
{
array[i] = obj;
continue;
}
if (parameterType == typeof(ushort) && obj is int num && num >= 0 && num <= 65535)
{
array[i] = (ushort)num;
continue;
}
if (parameterType == typeof(int) && obj is ushort num2)
{
array[i] = (int)num2;
continue;
}
if (parameterType == typeof(string))
{
array[i] = obj.ToString() ?? "";
continue;
}
return false;
}
args = array;
return true;
}
}
private static class Ui
{
private const string AuroraButtonName = "AuroraQuickConnect__PlayAuroraButton";
public static void TryInjectPlayAuroraButtonAboveStart(FejdStartup fs, Action onClick)
{
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_0169: Expected O, but got Unknown
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Expected O, but got Unknown
if ((Object)(object)fs == (Object)null || ((Component)fs).GetComponentsInChildren<Transform>(true).Any((Transform t) => ((Object)t).name == "AuroraQuickConnect__PlayAuroraButton"))
{
return;
}
Button[] componentsInChildren = ((Component)fs).GetComponentsInChildren<Button>(true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
Log.LogWarning((object)"No UI Buttons found under FejdStartup. Can't inject Play Aurora.");
return;
}
Button val = ((IEnumerable<Button>)componentsInChildren).FirstOrDefault((Func<Button, bool>)((Button b) => LabelContains(((Component)b).gameObject, "Start Game"))) ?? ((IEnumerable<Button>)componentsInChildren).FirstOrDefault((Func<Button, bool>)((Button b) => LabelContains(((Component)b).gameObject, "Start"))) ?? ((IEnumerable<Button>)componentsInChildren).FirstOrDefault((Func<Button, bool>)((Button b) => HasAnyLabel(((Component)b).gameObject))) ?? componentsInChildren[0];
Transform parent = ((Component)val).transform.parent;
GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject, parent);
((Object)val2).name = "AuroraQuickConnect__PlayAuroraButton";
val2.SetActive(true);
val2.transform.SetSiblingIndex(0);
SetButtonLabel(val2, _buttonText);
Button component = val2.GetComponent<Button>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val2);
return;
}
component.onClick = new ButtonClickedEvent();
((UnityEvent)component.onClick).AddListener(new UnityAction(onClick.Invoke));
Log.LogInfo((object)("Injected '" + _buttonText + "' button (template='" + ((Object)val).name + "')."));
}
public static bool TryInvokeVoidBestEffort(object instance, string methodName)
{
string methodName2 = methodName;
try
{
Type type = instance.GetType();
MethodInfo[] array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where m.Name == methodName2 && m.ReturnType == typeof(void)
select m).ToArray();
if (array.Length == 0)
{
return false;
}
MethodInfo methodInfo = array.FirstOrDefault((MethodInfo m) => m.GetParameters().Length == 0);
if (methodInfo != null)
{
methodInfo.Invoke(instance, Array.Empty<object>());
return true;
}
MethodInfo methodInfo2 = array.FirstOrDefault((MethodInfo m) => m.GetParameters().Length == 1);
if (methodInfo2 != null)
{
Type parameterType = methodInfo2.GetParameters()[0].ParameterType;
object obj = null;
if (parameterType == typeof(bool))
{
obj = false;
}
else if (parameterType == typeof(int))
{
obj = 0;
}
else if (parameterType == typeof(float))
{
obj = 0f;
}
else
{
if (!(parameterType == typeof(string)))
{
return false;
}
obj = "";
}
methodInfo2.Invoke(instance, new object[1] { obj });
return true;
}
}
catch
{
}
return false;
}
public static bool ClickButtonByLabel(FejdStartup fs, string[] include, string[] exclude)
{
Button val = FindButtonByLabel(fs, include, exclude);
if ((Object)(object)val == (Object)null)
{
return false;
}
ButtonClickedEvent onClick = val.onClick;
if (onClick != null)
{
((UnityEvent)onClick).Invoke();
}
return true;
}
private static Button? FindButtonByLabel(FejdStartup fs, string[] include, string[] exclude)
{
if ((Object)(object)fs == (Object)null)
{
return null;
}
Button[] componentsInChildren = ((Component)fs).GetComponentsInChildren<Button>(true);
if (componentsInChildren == null)
{
return null;
}
Button[] array = componentsInChildren;
foreach (Button val in array)
{
if ((Object)(object)val == (Object)null || !((Component)val).gameObject.activeInHierarchy)
{
continue;
}
string anyLabelText = GetAnyLabelText(((Component)val).gameObject);
if (!string.IsNullOrEmpty(anyLabelText))
{
string lower = anyLabelText.ToLowerInvariant();
if (!exclude.Any((string e) => lower.Contains(e.ToLowerInvariant())) && include.All((string i) => lower.Contains(i.ToLowerInvariant())))
{
return val;
}
}
}
return null;
}
public static void TryFillJoinByIp(FejdStartup fs, string hostAndPort, string password)
{
TrySetInputByFieldName(fs, new string[7] { "m_joinIPAddress", "m_joinIpAddress", "m_joinIP", "m_joinIp", "m_serverIP", "m_serverAddress", "m_serverHost" }, hostAndPort);
if (!string.IsNullOrEmpty(password))
{
TrySetInputByFieldName(fs, new string[4] { "m_joinPassword", "m_password", "m_serverPassword", "m_joinServerPassword" }, password);
}
}
private static void TrySetInputByFieldName(object instance, string[] fieldNames, string value)
{
foreach (string text in fieldNames)
{
try
{
FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), text);
if (fieldInfo == null)
{
continue;
}
object value2 = fieldInfo.GetValue(instance);
if (value2 != null)
{
InputField val = (InputField)((value2 is InputField) ? value2 : null);
if (val != null)
{
val.text = value;
break;
}
Type type = value2.GetType();
if (type.Name == "TMP_InputField")
{
type.GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.SetValue(value2, value);
break;
}
}
}
catch
{
}
}
}
private static bool LabelContains(GameObject go, string text)
{
string anyLabelText = GetAnyLabelText(go);
return anyLabelText != null && anyLabelText.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0;
}
private static bool HasAnyLabel(GameObject go)
{
return !string.IsNullOrEmpty(GetAnyLabelText(go));
}
private static string? GetAnyLabelText(GameObject go)
{
if ((Object)(object)go == (Object)null)
{
return null;
}
try
{
Component val = ((IEnumerable<Component>)go.GetComponentsInChildren<Component>(true)).FirstOrDefault((Func<Component, bool>)((Component c) => (Object)(object)c != (Object)null && (((object)c).GetType().Name == "TMP_Text" || ((object)c).GetType().Name == "TextMeshProUGUI")));
if ((Object)(object)val != (Object)null)
{
string text = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.GetValue(val) as string;
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
catch
{
}
Text componentInChildren = go.GetComponentInChildren<Text>(true);
if ((Object)(object)componentInChildren != (Object)null && !string.IsNullOrEmpty(componentInChildren.text))
{
return componentInChildren.text;
}
return null;
}
private static void SetButtonLabel(GameObject buttonGo, string label)
{
if ((Object)(object)buttonGo == (Object)null)
{
return;
}
try
{
Component val = ((IEnumerable<Component>)buttonGo.GetComponentsInChildren<Component>(true)).FirstOrDefault((Func<Component, bool>)((Component c) => (Object)(object)c != (Object)null && (((object)c).GetType().Name == "TMP_Text" || ((object)c).GetType().Name == "TextMeshProUGUI")));
if ((Object)(object)val != (Object)null)
{
((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public)?.SetValue(val, label);
return;
}
}
catch
{
}
Text componentInChildren = buttonGo.GetComponentInChildren<Text>(true);
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.text = label;
}
}
}
[CompilerGenerated]
private sealed class <ConnectToServerRoutine>d__32 : IEnumerator<object>, IDisposable, IEnumerator
{
private int <>1__state;
private object <>2__current;
public FejdStartup fs;
private string <hostAndPort>5__1;
private int <attempt>5__2;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ConnectToServerRoutine>d__32(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<hostAndPort>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Expected O, but got Unknown
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_015b: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = null;
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if (_uiSettleDelay > 0f)
{
<>2__current = (object)new WaitForSecondsRealtime(_uiSettleDelay);
<>1__state = 2;
return true;
}
goto IL_007b;
case 2:
<>1__state = -1;
goto IL_007b;
case 3:
{
<>1__state = -1;
<attempt>5__2++;
break;
}
IL_007b:
<hostAndPort>5__1 = $"{_host}:{_port}";
Log.LogInfo((object)("Aurora QuickConnect: attempting direct join to " + <hostAndPort>5__1));
<attempt>5__2 = 1;
break;
}
if (<attempt>5__2 <= _joinAttempts)
{
if (<attempt>5__2 == 1)
{
Log.LogInfo((object)$"Join attempt 1/{_joinAttempts}");
}
else
{
Log.LogInfo((object)$"Join attempt {<attempt>5__2}/{_joinAttempts}");
}
if (Joiner.TryJoin(fs, _host, _port, _password))
{
Log.LogInfo((object)"Aurora QuickConnect: join triggered successfully.");
return false;
}
<>2__current = (object)new WaitForSecondsRealtime(_joinAttemptInterval);
<>1__state = 3;
return true;
}
Log.LogWarning((object)"Aurora QuickConnect: Failed to start connection (no compatible join method found).");
if (_debugDumpOnFail)
{
Log.LogWarning((object)"Dumping join diagnostics (Debug.DumpJoinMethodsOnFail=true) ...");
Joiner.DumpJoinMethods(fs);
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public const string PluginGuid = "com.aurora.quickconnect";
public const string PluginName = "AuroraQuickConnect";
public const string PluginVersion = "1.0.0";
private static ManualLogSource Log = null;
private static Harmony _harmony = null;
private static bool _pending;
private static Coroutine? _connectRoutine;
private static string _host = "85.206.119.102";
private static int _port = 2456;
private static string _password = "";
private static string _buttonText = "Play Aurora";
private static int _joinAttempts = 10;
private static float _joinAttemptInterval = 0.25f;
private static float _uiSettleDelay = 0.15f;
private static bool _debugDumpOnFail = true;
private ConfigEntry<string> _cfgHost = null;
private ConfigEntry<int> _cfgPort = null;
private ConfigEntry<string> _cfgPassword = null;
private ConfigEntry<string> _cfgButtonText = null;
private ConfigEntry<int> _cfgJoinAttempts = null;
private ConfigEntry<float> _cfgJoinAttemptInterval = null;
private ConfigEntry<float> _cfgUiSettleDelay = null;
private ConfigEntry<bool> _cfgDebugDumpOnFail = null;
private void Awake()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
try
{
SetupConfig();
_harmony = new Harmony("com.aurora.quickconnect");
PatchIfExists(typeof(FejdStartup), "Start", null, "FejdStartup_Start_Postfix");
PatchIfExists(typeof(FejdStartup), "OnCharacterStart", "FejdStartup_OnCharacterStart_Prefix");
PatchIfExists(typeof(FejdStartup), "OnBack", null, "FejdStartup_Back_Postfix");
PatchIfExists(typeof(FejdStartup), "OnBackButton", null, "FejdStartup_Back_Postfix");
PatchIfExists(typeof(FejdStartup), "OnCancel", null, "FejdStartup_Back_Postfix");
Log.LogInfo((object)string.Format("{0} {1} loaded. Target={2}:{3} (password={4}).", "AuroraQuickConnect", "1.0.0", _host, _port, string.IsNullOrEmpty(_password) ? "none" : "set"));
}
catch (Exception arg)
{
Log.LogError((object)string.Format("{0} failed to load: {1}", "AuroraQuickConnect", arg));
}
}
private void OnDestroy()
{
try
{
Harmony harmony = _harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
}
catch
{
}
}
private void SetupConfig()
{
_cfgHost = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "Host", "85.206.119.102", "Server IP / hostname for Aurora.");
_cfgPort = ((BaseUnityPlugin)this).Config.Bind<int>("Server", "Port", 2456, "Server port for Aurora.");
_cfgPassword = ((BaseUnityPlugin)this).Config.Bind<string>("Server", "Password", "", "Server password (leave blank if none).");
_cfgButtonText = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "ButtonText", "Play Aurora", "Text shown on the main-menu button.");
_cfgJoinAttempts = ((BaseUnityPlugin)this).Config.Bind<int>("Connect", "JoinAttempts", 10, "How many times to try triggering a join (safe retries, no spam).");
_cfgJoinAttemptInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Connect", "AttemptIntervalSeconds", 0.25f, "Seconds between join attempts.");
_cfgUiSettleDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Connect", "UiSettleDelaySeconds", 0.15f, "Small delay after clicking Start, before we trigger the join.");
_cfgDebugDumpOnFail = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DumpJoinMethodsOnFail", true, "If join cannot be triggered, print join/connect method info to the log.");
ApplyConfigSnapshot();
_cfgHost.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgPort.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgPassword.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgButtonText.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgJoinAttempts.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgJoinAttemptInterval.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgUiSettleDelay.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
_cfgDebugDumpOnFail.SettingChanged += delegate
{
ApplyConfigSnapshot();
};
try
{
((BaseUnityPlugin)this).Config.Save();
Log.LogInfo((object)("Config ready: " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
}
catch (Exception ex)
{
Log.LogWarning((object)("Could not save config file: " + ex.GetType().Name + ": " + ex.Message));
}
}
private void ApplyConfigSnapshot()
{
_host = _cfgHost.Value?.Trim() ?? "85.206.119.102";
_port = _cfgPort.Value;
if (_port <= 0 || _port > 65535)
{
_port = 2456;
}
_password = _cfgPassword.Value ?? "";
_buttonText = (string.IsNullOrWhiteSpace(_cfgButtonText.Value) ? "Play Aurora" : _cfgButtonText.Value);
_joinAttempts = _cfgJoinAttempts.Value;
if (_joinAttempts < 1)
{
_joinAttempts = 1;
}
if (_joinAttempts > 50)
{
_joinAttempts = 50;
}
_joinAttemptInterval = _cfgJoinAttemptInterval.Value;
if (_joinAttemptInterval < 0.05f)
{
_joinAttemptInterval = 0.05f;
}
if (_joinAttemptInterval > 5f)
{
_joinAttemptInterval = 5f;
}
_uiSettleDelay = _cfgUiSettleDelay.Value;
if (_uiSettleDelay < 0f)
{
_uiSettleDelay = 0f;
}
if (_uiSettleDelay > 5f)
{
_uiSettleDelay = 5f;
}
_debugDumpOnFail = _cfgDebugDumpOnFail.Value;
}
private static void PatchIfExists(Type type, string methodName, string? prefix = null, string? postfix = null)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
try
{
MethodInfo methodInfo = AccessTools.Method(type, methodName, (Type[])null, (Type[])null);
if (methodInfo == null)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[PatchIfExists] " + type.Name + "." + methodName + " not found on this client build. Skipping."));
}
}
else
{
HarmonyMethod val = ((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Class1), prefix, (Type[])null));
HarmonyMethod val2 = ((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(Class1), postfix, (Type[])null));
_harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogInfo((object)("Patched " + type.Name + "." + methodName));
}
}
}
catch (Exception ex)
{
ManualLogSource log3 = Log;
if (log3 != null)
{
log3.LogWarning((object)("[PatchIfExists] Failed patching " + type.Name + "." + methodName + ": " + ex.GetType().Name + ": " + ex.Message));
}
}
}
private static void FejdStartup_Start_Postfix(FejdStartup __instance)
{
FejdStartup __instance2 = __instance;
try
{
Ui.TryInjectPlayAuroraButtonAboveStart(__instance2, delegate
{
OnPlayAuroraClicked(__instance2);
});
}
catch (Exception arg)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)$"Button injection exception: {arg}");
}
}
}
private static bool FejdStartup_OnCharacterStart_Prefix(FejdStartup __instance)
{
if (!_pending)
{
return true;
}
_pending = false;
Log.LogInfo((object)$"OnCharacterStart intercepted (Play Aurora) -> joining {_host}:{_port}");
if (_connectRoutine != null)
{
try
{
((MonoBehaviour)__instance).StopCoroutine(_connectRoutine);
}
catch
{
}
_connectRoutine = null;
}
_connectRoutine = ((MonoBehaviour)__instance).StartCoroutine(ConnectToServerRoutine(__instance));
return false;
}
private static void FejdStartup_Back_Postfix()
{
_pending = false;
}
private static void OnPlayAuroraClicked(FejdStartup fs)
{
Log.LogInfo((object)"Play Aurora clicked.");
_pending = true;
if (!Ui.TryInvokeVoidBestEffort(fs, "OnStartGame") && !Ui.TryInvokeVoidBestEffort(fs, "OnStart") && !Ui.ClickButtonByLabel(fs, new string[2] { "start", "game" }, Array.Empty<string>()))
{
Log.LogWarning((object)"Couldn't open Character Select automatically. Click Valheim's Start Game once, then click Play Aurora again.");
_pending = false;
}
}
[IteratorStateMachine(typeof(<ConnectToServerRoutine>d__32))]
private static IEnumerator ConnectToServerRoutine(FejdStartup fs)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ConnectToServerRoutine>d__32(0)
{
fs = fs
};
}
}
}