using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("QuickConnect")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("QuickConnect")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("1c6b0fc4-ad65-4bb6-a9db-7ca3b47eadf6")]
[assembly: AssemblyFileVersion("1.5.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.5.0.0")]
namespace QuickConnect;
[HarmonyPatch(typeof(ZNet), "RPC_ClientHandshake")]
internal class PatchPasswordPrompt
{
private static bool Prefix(ZNet __instance, ZRpc rpc, bool needPassword, string serverPasswordSalt)
{
string text = QuickConnectUI.instance.CurrentPass();
if (text != null)
{
if (needPassword)
{
Mod.Log.LogInfo((object)"Authenticating with saved password...");
((Component)__instance.m_connectingDialog).gameObject.SetActive(false);
FieldInfo field = typeof(ZNet).GetField("m_serverPasswordSalt", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, serverPasswordSalt);
MethodInfo method = typeof(ZNet).GetMethod("SendPeerInfo", BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(__instance, new object[2] { rpc, text });
return false;
}
Mod.Log.LogInfo((object)"Server didn't want password?");
}
return true;
}
}
[HarmonyPatch(typeof(ZSteamMatchmaking), "OnJoinServerFailed")]
internal class PatchConnectFailed
{
private static void Postfix()
{
if (Object.op_Implicit((Object)(object)QuickConnectUI.instance))
{
QuickConnectUI.instance.JoinServerFailed();
}
}
}
[HarmonyPatch(typeof(FejdStartup), "OnSelelectCharacterBack")]
internal class PatchCharacterBack
{
private static void Postfix()
{
if (Object.op_Implicit((Object)(object)QuickConnectUI.instance))
{
QuickConnectUI.instance.AbortConnect();
}
}
}
[HarmonyPatch(typeof(FejdStartup), "SetupGui")]
internal class PatchUiInit
{
private static void Postfix()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
if (!Object.op_Implicit((Object)(object)QuickConnectUI.instance))
{
Servers.Init();
GameObject val = new GameObject("QuickConnect");
QuickConnectUI.instance = val.AddComponent<QuickConnectUI>();
}
}
}
[BepInPlugin("net.bdew.valheim.QuickConnect", "QuickConnect", "1.6.0")]
internal class Mod : BaseUnityPlugin
{
public static ManualLogSource Log;
public static ConfigEntry<float> windowPosX;
public static ConfigEntry<float> windowPosY;
public static ConfigEntry<int> buttonFontSize;
public static ConfigEntry<int> labelFontSize;
public static ConfigEntry<int> windowWidth;
public static ConfigEntry<int> windowHeight;
private void Awake()
{
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00d0: Expected O, but got Unknown
Log = Logger.CreateLogSource("QuickConnect");
windowPosX = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPosX", 20f, (ConfigDescription)null);
windowPosY = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "WindowPosY", 20f, (ConfigDescription)null);
buttonFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "ButtonFontSize", 0, (ConfigDescription)null);
labelFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "LabelFontSize", 0, (ConfigDescription)null);
windowWidth = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "WindowWidth", 250, (ConfigDescription)null);
windowHeight = ((BaseUnityPlugin)this).Config.Bind<int>("UI", "WindowHeight", 50, (ConfigDescription)null);
Harmony val = new Harmony("net.bdew.valheim.QuickConnect");
val.PatchAll();
}
}
internal class QuickConnectUI : MonoBehaviour
{
public static QuickConnectUI instance;
private Rect windowRect;
private Rect lastRect;
private Rect errorWinRect;
private Rect dragRect = new Rect(0f, 0f, 10000f, 20f);
private int buttonFontSize;
private int labelFontSize;
private GUIStyle buttonStyle;
private GUIStyle labelStyle;
private Task<IPHostEntry> resolveTask;
private Servers.Entry connecting;
private string errorMsg;
private void Update()
{
if (resolveTask == null)
{
return;
}
if (resolveTask.IsFaulted)
{
Mod.Log.LogError((object)$"Error resolving IP: {resolveTask.Exception}");
if (resolveTask.Exception != null)
{
ShowError(resolveTask.Exception.InnerException.Message);
}
else
{
ShowError(resolveTask.Exception.Message);
}
resolveTask = null;
connecting = null;
}
else if (resolveTask.IsCanceled)
{
resolveTask = null;
connecting = null;
}
else
{
if (!resolveTask.IsCompleted)
{
return;
}
IPAddress[] addressList = resolveTask.Result.AddressList;
foreach (IPAddress iPAddress in addressList)
{
if (iPAddress.AddressFamily == AddressFamily.InterNetwork)
{
Mod.Log.LogInfo((object)$"Resolved: {iPAddress}");
resolveTask = null;
ZSteamMatchmaking.instance.QueueServerJoin($"{iPAddress}:{connecting.port}");
return;
}
}
resolveTask = null;
connecting = null;
ShowError("Server DNS resolved to no valid addresses");
}
}
private void Awake()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
((Rect)(ref windowRect)).x = Mod.windowPosX.Value;
((Rect)(ref windowRect)).y = Mod.windowPosY.Value;
buttonFontSize = Mod.buttonFontSize.Value;
labelFontSize = Mod.labelFontSize.Value;
((Rect)(ref windowRect)).width = Mod.windowWidth.Value;
((Rect)(ref windowRect)).height = Mod.windowHeight.Value;
lastRect = windowRect;
}
private void OnGUI()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Expected O, but got Unknown
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Expected O, but got Unknown
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: 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_0093: Expected O, but got Unknown
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
if (buttonStyle == null)
{
buttonStyle = new GUIStyle(GUI.skin.button);
buttonStyle.fontSize = buttonFontSize;
labelStyle = new GUIStyle(GUI.skin.label);
labelStyle.fontSize = labelFontSize;
}
if (errorMsg != null)
{
errorWinRect = GUILayout.Window(1586464, errorWinRect, new WindowFunction(DrawErrorWindow), "Error", Array.Empty<GUILayoutOption>());
return;
}
windowRect = GUILayout.Window(1586463, windowRect, new WindowFunction(DrawConnectWindow), "Quick Connect", Array.Empty<GUILayoutOption>());
if (!((Rect)(ref lastRect)).Equals(windowRect))
{
Mod.windowPosX.Value = ((Rect)(ref windowRect)).x;
Mod.windowPosY.Value = ((Rect)(ref windowRect)).y;
lastRect = windowRect;
}
}
private void DrawConnectWindow(int windowID)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
GUI.DragWindow(dragRect);
if (connecting != null)
{
GUILayout.Label("Connecting to " + connecting.name, labelStyle, Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Cancel", buttonStyle, Array.Empty<GUILayoutOption>()))
{
AbortConnect();
}
return;
}
if (Servers.entries.Count > 0)
{
GUILayout.Label("Choose A Server:", labelStyle, Array.Empty<GUILayoutOption>());
{
foreach (Servers.Entry entry in Servers.entries)
{
if (GUILayout.Button(entry.name, buttonStyle, Array.Empty<GUILayoutOption>()))
{
DoConnect(entry);
}
}
return;
}
}
GUILayout.Label("No servers defined", labelStyle, Array.Empty<GUILayoutOption>());
GUILayout.Label("Add quick_connect_servers.cfg", labelStyle, Array.Empty<GUILayoutOption>());
}
private void DrawErrorWindow(int windowID)
{
GUILayout.Label(errorMsg, labelStyle, Array.Empty<GUILayoutOption>());
if (GUILayout.Button("Close", buttonStyle, Array.Empty<GUILayoutOption>()))
{
errorMsg = null;
}
}
private void DoConnect(Servers.Entry server)
{
connecting = server;
try
{
IPAddress.Parse(server.ip);
ZSteamMatchmaking.instance.QueueServerJoin($"{server.ip}:{server.port}");
}
catch (FormatException)
{
Mod.Log.LogInfo((object)("Resolving: " + server.ip));
resolveTask = Dns.GetHostEntryAsync(server.ip);
}
}
public string CurrentPass()
{
if (connecting != null)
{
return connecting.pass;
}
return null;
}
public void JoinServerFailed()
{
ShowError("Server connection failed");
connecting = null;
}
public void ShowError(string msg)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
errorMsg = msg;
errorWinRect = new Rect((float)(Screen.width / 2 - 125), (float)(Screen.height / 2), 250f, 30f);
}
public void AbortConnect()
{
connecting = null;
resolveTask = null;
}
}
internal class Servers
{
public class Entry
{
public string name;
public string ip;
public int port;
public string pass;
public override string ToString()
{
return string.Format("Server(name={0},ip={1},port={2}}", name, ip, port);
}
}
public static string ConfigPath;
public static List<Entry> entries;
public static void Init()
{
entries.Clear();
try
{
if (!File.Exists(ConfigPath))
{
return;
}
using StreamReader streamReader = new StreamReader(ConfigPath);
string text;
while ((text = streamReader.ReadLine()) != null)
{
text = text.Trim();
if (text.Length == 0 || text.StartsWith("#"))
{
continue;
}
string[] array = text.Split(new char[1] { ':' });
if (array.Length >= 3)
{
string name = array[0];
string ip = array[1];
int port = int.Parse(array[2]);
string pass = null;
if (array.Length >= 4)
{
pass = array[3];
}
entries.Add(new Entry
{
name = name,
ip = ip,
port = port,
pass = pass
});
}
else
{
Mod.Log.LogWarning((object)("Invalid config line: " + text));
}
}
Mod.Log.LogInfo((object)$"Loaded {entries.Count} server entries");
}
catch (Exception arg)
{
Mod.Log.LogError((object)$"Error loading config {arg}");
}
}
static Servers()
{
string? directoryName = Path.GetDirectoryName(Paths.BepInExConfigPath);
char directorySeparatorChar = Path.DirectorySeparatorChar;
ConfigPath = directoryName + directorySeparatorChar + "quick_connect_servers.cfg";
entries = new List<Entry>();
}
}