using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using AtlyssDedicatedServer.HarmonyPatches;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Steamworks;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("BepInEx")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FleesDedicatedServer")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+05665ebd994e2f33b7f66369d861ea754e063df0")]
[assembly: AssemblyProduct("DedicatedServer")]
[assembly: AssemblyTitle("FleesDedicatedServer")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
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;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace AtlyssDedicatedServer
{
public class ConsoleListenerWithInput : ILogListener, IDisposable
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ConsoleLogListener <original>P;
public readonly StringBuilder Input;
private static readonly object _consoleLock = new object();
private static string WindowWidthString = "";
public ConsoleListenerWithInput(ConsoleLogListener original)
{
<original>P = original;
Input = new StringBuilder();
base..ctor();
}
public void Dispose()
{
<original>P.Dispose();
}
public void LogEvent(object sender, LogEventArgs eventArgs)
{
ClearInputLine();
<original>P.LogEvent(sender, eventArgs);
DrawInputPrompt();
}
private void ClearInputLine()
{
int num = Math.Max(Console.WindowWidth - 1, 0);
if (WindowWidthString.Length != num)
{
WindowWidthString = new string(' ', num);
}
ConsoleManager.StandardOutStream.Write('\r');
ConsoleManager.StandardOutStream.Write(WindowWidthString);
ConsoleManager.StandardOutStream.Write('\r');
}
private void DrawInputPrompt()
{
lock (_consoleLock)
{
ConsoleManager.StandardOutStream.Write("> ");
ConsoleManager.StandardOutStream.Write(Input.ToString());
ConsoleManager.StandardOutStream.Flush();
}
}
public void ProcessInput()
{
if (!Console.KeyAvailable)
{
return;
}
ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(intercept: true);
lock (_consoleLock)
{
switch (consoleKeyInfo.Key)
{
case ConsoleKey.Enter:
{
string text = Input.ToString();
Input.Clear();
ConsoleManager.StandardOutStream.WriteLine();
HostConsole._current.Send_ServerMessage(text);
ClearInputLine();
DrawInputPrompt();
break;
}
case ConsoleKey.Backspace:
if (Input.Length > 0)
{
Input.Length--;
ClearInputLine();
DrawInputPrompt();
}
break;
default:
if (!char.IsControl(consoleKeyInfo.KeyChar))
{
Input.Append(consoleKeyInfo.KeyChar);
ConsoleManager.StandardOutStream.Write(consoleKeyInfo.KeyChar);
}
break;
}
}
}
}
[BepInPlugin("FleesDedicatedServer", "DedicatedServer", "0.1.0")]
[BepInProcess("ATLYSS.exe")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Logger;
internal static ServerHandler Handler;
internal static ConsoleListenerWithInput ConsoleListener;
private Plugin()
{
Logger = ((BaseUnityPlugin)this).Logger;
}
private void GenerateLaunchScripts()
{
string directoryName = Path.GetDirectoryName(Paths.ExecutablePath);
File.WriteAllText(Path.Combine(directoryName, "steam_appid.txt"), "2768430");
if (WineDetect.IsRunningInWine)
{
string environmentVariable = Environment.GetEnvironmentVariable("STEAM_COMPAT_DATA_PATH");
string environmentVariable2 = Environment.GetEnvironmentVariable("STEAM_COMPAT_CLIENT_INSTALL_PATH");
string text = Environment.GetEnvironmentVariable("STEAM_COMPAT_TOOL_PATHS")?.Split(":").FirstOrDefault((string x) => x.Contains("/Proton"));
string text2 = Paths.ExecutablePath.Replace('\\', '/');
if (text2.IndexOf(':') != -1)
{
text2 = text2.Substring(text2.IndexOf(':') + 1);
}
if (string.IsNullOrWhiteSpace(environmentVariable) || string.IsNullOrWhiteSpace(environmentVariable2) || string.IsNullOrWhiteSpace(text))
{
Logger.LogWarning((object)"Couldn't generate a dedicated server launch script for Linux w/ Proton!");
return;
}
File.WriteAllText(Path.Combine(directoryName, "start_dedicated_server.sh"), "export STEAM_COMPAT_DATA_PATH=" + environmentVariable + "\nexport STEAM_COMPAT_CLIENT_INSTALL_PATH=" + environmentVariable2 + "\n" + string.Join(" ", "\"" + text + "/proton\"", "run", "\"" + text2 + "\"", "-batchmode", "-nographics", "-server", "--doorstop-enabled", "true", "--doorstop-target-assembly", "\"" + Path.Combine(Paths.BepInExAssemblyDirectory, "BepInEx.Preloader.dll") + "\"", "&"));
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
File.WriteAllText(Path.Combine(directoryName, "start_dedicated_server.cmd"), string.Join(" ", "start", "\"Launch Dedicated Server\"", "\"" + Paths.ExecutablePath + "\"", "-batchmode", "-nographics", "-server", "--doorstop-enabled", "true", "--doorstop-target-assembly", "\"" + Path.Combine(Paths.BepInExAssemblyDirectory, "BepInEx.Preloader.dll") + "\""));
}
else
{
Logger.LogWarning((object)"Couldn't generate a dedicated server launch script for current platform!");
}
}
private void Awake()
{
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Expected O, but got Unknown
PluginConfig.Configure(((BaseUnityPlugin)this).Config, Environment.GetCommandLineArgs());
GenerateLaunchScripts();
if (!PluginConfig.IsActive)
{
Logger.LogInfo((object)"Argument \"-server\" not found; starting in normal mode.");
return;
}
Logger.LogInfo((object)"Starting in dedicated server mode.");
Logger.LogInfo((object)("Headless mode is " + (PluginConfig.IsHeadless ? "on" : "off") + "."));
GameObject val = new GameObject("DedicatedServer");
Object.DontDestroyOnLoad((Object)(object)val);
Handler = val.AddComponent<ServerHandler>();
Console.CursorVisible = true;
try
{
ICollection<ILogListener> listeners = Logger.Listeners;
ILogListener? obj = ((IEnumerable<ILogListener>)listeners).FirstOrDefault((Func<ILogListener, bool>)((ILogListener l) => ((object)l).GetType() == typeof(ConsoleLogListener)));
ConsoleLogListener val2 = (ConsoleLogListener)(object)((obj is ConsoleLogListener) ? obj : null);
if (val2 != null)
{
listeners.Remove((ILogListener)(object)val2);
Logger.Listeners.Add((ILogListener)(object)(ConsoleListener = new ConsoleListenerWithInput(val2)));
Logger.LogInfo((object)"Successfully detached default BepInEx console listener.");
}
}
catch (Exception arg)
{
Logger.LogError((object)$"An error occurred while accessing the console stream: {arg}");
}
if (PluginConfig.IsHeadless)
{
AudioListener.volume = 0f;
PreventAudioChanges.LockAudio = true;
}
Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
}
}
internal static class PluginConfig
{
internal static string ServerName { get; private set; }
internal static SteamLobbyType ServerType { get; private set; }
internal static AtlyssSteamLobbyTag ServerTag { get; private set; }
internal static string ServerPassword { get; private set; }
internal static string ServerMOTD { get; private set; }
internal static int ServerMaxPlayers { get; private set; }
internal static int CharacterSlotToUse { get; private set; }
internal static bool PeriodicRestartEnabled { get; private set; }
internal static string PeriodicRestartInterval { get; private set; }
internal static int PeriodicRestartPlayerThresholdPercent { get; private set; }
internal static bool IsActive { get; private set; }
internal static bool IsHeadless { get; private set; }
internal static int PeriodicRestartIntervalSeconds { get; private set; }
internal static int PeriodicRestartPlayerThreshold { get; private set; }
public static void Configure(ConfigFile file, string[] args)
{
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
IsActive = args.Contains("-server");
IsHeadless = IsActive && Application.isBatchMode && args.Contains("-nographics");
ServerName = file.Bind<string>("ServerData", "ServerName", "ATLYSS Server", "Name to set when launching the server.").Value;
if (TryGetStringArgment(args, "-pve", out string value))
{
ServerName = value;
}
if (ServerName.Length > 20)
{
Plugin.Logger.LogWarning((object)$"Server name \"{ServerName}\" is too long ({ServerName.Length}/20). Defaulting to \"ATLYSS Server\".");
ServerName = "ATLYSS Server";
}
if (string.IsNullOrWhiteSpace(ServerName))
{
Plugin.Logger.LogWarning((object)("Server name \"" + ServerName + "\" is invalid. Defaulting to \"ATLYSS Server\"."));
ServerName = "ATLYSS Server";
}
ServerType = file.Bind<SteamLobbyType>("ServerData", "ServerType", SteamLobbyType.PUBLIC, "Type to set when launching the server.").Value;
if (args.Contains("-public"))
{
ServerType = SteamLobbyType.PUBLIC;
}
else if (args.Contains("-friends"))
{
ServerType = SteamLobbyType.FRIENDS;
}
else if (args.Contains("-private"))
{
ServerType = SteamLobbyType.PRIVATE;
}
ServerTag = file.Bind<AtlyssSteamLobbyTag>("ServerData", "ServerTag", (AtlyssSteamLobbyTag)0, "Lobby tag to set when launching the server.").Value;
if (args.Contains("-pve"))
{
ServerTag = (AtlyssSteamLobbyTag)0;
}
else if (args.Contains("-pvp"))
{
ServerTag = (AtlyssSteamLobbyTag)1;
}
else if (args.Contains("-social"))
{
ServerTag = (AtlyssSteamLobbyTag)2;
}
else if (args.Contains("-rp"))
{
ServerTag = (AtlyssSteamLobbyTag)3;
}
ServerPassword = file.Bind<string>("ServerData", "ServerPassword", "", "Password to use for connecting to the server. Leave empty for a passwordless server.").Value;
if (TryGetStringArgment(args, "-password", out string value2))
{
ServerPassword = value2;
}
ServerMOTD = file.Bind<string>("ServerData", "ServerMOTD", "Welcome to ATLYSS Server!", "MOTD to display for clients that connect to the server.").Value;
if (TryGetStringArgment(args, "-motd", out string value3))
{
ServerMOTD = value3;
}
ServerMaxPlayers = file.Bind<int>("ServerData", "ServerMaxPlayers", 16, "Maximum number of players that can connect to the server (this includes the dummy host player).").Value;
if (TryGetIntegerArgment(args, "-maxplayers", out var value4))
{
ServerMaxPlayers = value4;
}
if (ServerMaxPlayers < 2 || ServerMaxPlayers > 250)
{
ServerMaxPlayers = 16;
Plugin.Logger.LogWarning((object)"MaxPlayers must be between 2 and 250. Defaulting to 16.");
}
CharacterSlotToUse = file.Bind<int>("ServerData", "CharacterSlotToUse", 0, "Character slot to use for the (idle) host character. If the slot is empty, the first non-empty save slot will be used instead. If all slots are empty, a new randomized character will be created in the first slot.").Value;
if (TryGetIntegerArgment(args, "-hostsave", out var value5))
{
CharacterSlotToUse = value5;
}
PeriodicRestartEnabled = file.Bind<bool>("ServerHealth", "PeriodicRestartEnabled", false, "Enable restarting the server automatically after the given time interval and number of players left.").Value;
if (args.Contains("-autorestart"))
{
PeriodicRestartEnabled = true;
}
PeriodicRestartInterval = file.Bind<string>("ServerHealth", "PeriodicRestartInterval", "6h", "How much time to wait before restarting. Must be at least 30 minutes. Format is specified in days, hours, minutes and/or seconds like 1d12h30m30s, 4h45m, 4h, 30m, 1d, etc.").Value;
if (TryGetStringArgment(args, "-autorestartin", out string value6))
{
PeriodicRestartInterval = value6;
}
if (Utils.TryParseInterval(PeriodicRestartInterval, out var seconds))
{
if (seconds < 1800)
{
seconds = 1800;
Plugin.Logger.LogWarning((object)"Specified restart time is too low (<30m). Increasing it to 30 minutes.");
}
PeriodicRestartIntervalSeconds = seconds;
}
else
{
PeriodicRestartIntervalSeconds = 14400;
Plugin.Logger.LogWarning((object)"Specified restart time is invalid. Defaulting to 4 hours.");
}
PeriodicRestartPlayerThresholdPercent = file.Bind<int>("ServerHealth", "PeriodicRestartPlayerThresholdPercent", 100, "Theshold of players (% of MaxPlayers) with which the server will proceed with a periodic restart. If there are more players than that, the restart timer will be stalled at 1 minute left until enough players leave. Set to 100 to ignore player counts and always restart the server.").Value;
if (TryGetIntegerArgment(args, "-autorestartthreshold", out var value7))
{
PeriodicRestartPlayerThresholdPercent = value7;
}
if (0 > PeriodicRestartPlayerThresholdPercent || PeriodicRestartPlayerThresholdPercent > 100)
{
PeriodicRestartPlayerThresholdPercent = 100;
Plugin.Logger.LogWarning((object)"Specified restart player threshold is invalid. Defaulting to 100 (threshold disabled).");
}
PeriodicRestartPlayerThreshold = Math.Clamp((int)Math.Ceiling((float)(ServerMaxPlayers * PeriodicRestartPlayerThresholdPercent) / 100f), 1, ServerMaxPlayers);
file.Save();
}
private static bool TryGetStringArgment(string[] args, string key, [NotNullWhen(true)] out string? value)
{
int num = Array.IndexOf(args, key);
value = ((num >= 0 && num + 1 < args.Length) ? args[num + 1] : null);
return value != null;
}
private static bool TryGetIntegerArgment(string[] args, string key, out int value)
{
int num = Array.IndexOf(args, key);
string text = ((num >= 0 && num + 1 < args.Length) ? args[num + 1] : null);
if (text == null)
{
value = 0;
return false;
}
if (int.TryParse((num >= 0 && num + 1 < args.Length) ? args[num + 1] : null, out value))
{
return true;
}
Plugin.Logger.LogWarning((object)("Value \"" + text + "\" supplied to argument \"" + key + "\" is not a valid integer."));
return false;
}
}
public class ServerHandler : MonoBehaviour
{
[CompilerGenerated]
private sealed class <ServerHeartbeat>d__10 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public ServerHandler <>4__this;
private WaitForSeconds <oneSecond>5__1;
private bool <supressTimer>5__2;
private bool <shouldPrintMessage>5__3;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <ServerHeartbeat>d__10(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<oneSecond>5__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<oneSecond>5__1 = new WaitForSeconds(1f);
break;
case 1:
<>1__state = -1;
if (Object.op_Implicit((Object)(object)Player._mainPlayer) && !Player._mainPlayer._pVisual._forceHidden)
{
Player._mainPlayer._pVisual.Network_forceHidden = true;
}
if (Object.op_Implicit((Object)(object)MainMenuManager._current) && !NetworkServer.active && !NetworkClient.active)
{
<>4__this.StartServer();
<>2__current = <oneSecond>5__1;
<>1__state = 2;
return true;
}
if (NetworkServer.active && PluginConfig.PeriodicRestartEnabled && <>4__this.ShutdownSecondsLeft == 0)
{
<>4__this.ScheduleAutomaticRestart();
}
else
{
if (!NetworkServer.active || <>4__this.ShutdownSecondsLeft <= 0)
{
break;
}
<supressTimer>5__2 = false;
if (!<>4__this.IsAutomaticRestart || <>4__this.ShutdownSecondsLeft > 60 || <>4__this.PlayerThresholdReached)
{
<>4__this.ShutdownSecondsLeft--;
}
if (<>4__this.IsAutomaticRestart && <>4__this.ShutdownSecondsLeft <= 60 && !<>4__this.PlayerThresholdReached)
{
if (NetworkServer.connections.Count <= PluginConfig.PeriodicRestartPlayerThreshold)
{
<>4__this.PlayerThresholdReached = true;
}
else
{
<supressTimer>5__2 = true;
if (!<>4__this.PlayerThresholdNotified)
{
HostConsole._current.Init_ServerMessage($"Server will restart once there are {PluginConfig.PeriodicRestartPlayerThreshold} or less players remaining.");
<>4__this.PlayerThresholdNotified = true;
}
}
}
if (<supressTimer>5__2)
{
break;
}
if (<>4__this.ShutdownSecondsLeft == 0)
{
<>4__this.StopServer();
if (!<>4__this.ShouldRestart)
{
<>2__current = <oneSecond>5__1;
<>1__state = 3;
return true;
}
break;
}
<shouldPrintMessage>5__3 = <>4__this.ShutdownSecondsLeft <= 5 || (<>4__this.ShutdownSecondsLeft <= 60 && <>4__this.ShutdownSecondsLeft % 15 == 0) || (<>4__this.ShutdownSecondsLeft <= 300 && <>4__this.ShutdownSecondsLeft % 60 == 0) || (<>4__this.ShutdownSecondsLeft <= 900 && <>4__this.ShutdownSecondsLeft % 300 == 0) || (<>4__this.ShutdownSecondsLeft <= 3600 && <>4__this.ShutdownSecondsLeft % 900 == 0);
if (<shouldPrintMessage>5__3)
{
HostConsole._current.Init_ServerMessage("Server will " + (<>4__this.ShouldRestart ? "restart" : "shut down") + " in " + Utils.FormatInterval(<>4__this.ShutdownSecondsLeft) + ".");
}
}
break;
case 2:
<>1__state = -1;
break;
case 3:
<>1__state = -1;
Application.Quit();
return false;
}
<>2__current = <oneSecond>5__1;
<>1__state = 1;
return true;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private int ShutdownSecondsLeft;
private bool PlayerThresholdNotified;
private bool PlayerThresholdReached;
private bool ShouldRestart;
private bool IsAutomaticRestart;
private void Awake()
{
((MonoBehaviour)this).StartCoroutine(ServerHeartbeat());
}
public void ScheduleShutdown(int seconds)
{
ShutdownSecondsLeft = seconds;
PlayerThresholdNotified = false;
PlayerThresholdReached = false;
IsAutomaticRestart = false;
ShouldRestart = false;
HostConsole._current.Init_ServerMessage($"Server will shut down in {ShutdownSecondsLeft} seconds.");
}
public void ScheduleRestart(int seconds)
{
ShutdownSecondsLeft = seconds;
PlayerThresholdNotified = false;
PlayerThresholdReached = false;
IsAutomaticRestart = false;
ShouldRestart = true;
HostConsole._current.Init_ServerMessage($"Server will restart in {ShutdownSecondsLeft} seconds.");
}
public void ScheduleAutomaticRestart()
{
ShutdownSecondsLeft = PluginConfig.PeriodicRestartIntervalSeconds;
PlayerThresholdNotified = false;
PlayerThresholdReached = false;
IsAutomaticRestart = true;
ShouldRestart = true;
Plugin.Logger.LogInfo((object)("Scheduled automatic restart in " + Utils.FormatInterval(PluginConfig.PeriodicRestartIntervalSeconds) + "."));
}
public void CancelShutdownOrRestart()
{
if (ShutdownSecondsLeft == 0)
{
Plugin.Logger.LogInfo((object)"No pending shutdown or restart to cancel.");
return;
}
HostConsole._current.Init_ServerMessage((ShouldRestart ? "Restart" : "Shutdown") + " cancelled.");
ShutdownSecondsLeft = 0;
ShouldRestart = false;
}
[IteratorStateMachine(typeof(<ServerHeartbeat>d__10))]
private IEnumerator ServerHeartbeat()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <ServerHeartbeat>d__10(0)
{
<>4__this = this
};
}
internal void StopServer()
{
if (NetworkServer.active)
{
Plugin.Logger.LogInfo((object)"Stopping Server");
if (NetworkClient.isConnected)
{
((NetworkManager)AtlyssNetworkManager._current).StopHost();
}
else
{
((NetworkManager)AtlyssNetworkManager._current).StopServer();
}
}
}
internal void StartServer()
{
//IL_00a4: 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_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogInfo((object)"Starting Server");
LogServerConfig();
ServerHostSettings_Profile hostSettingsProfile = ProfileDataManager._current._hostSettingsProfile;
AtlyssNetworkManager current = AtlyssNetworkManager._current;
ProfileDataManager current2 = ProfileDataManager._current;
LobbyListManager current3 = LobbyListManager._current;
current._steamworksMode = true;
current._soloMode = false;
current._serverMode = false;
current._serverName = PluginConfig.ServerName;
current._serverPassword = PluginConfig.ServerPassword;
current._sentPassword = PluginConfig.ServerPassword;
current._serverMotd = PluginConfig.ServerMOTD;
((NetworkManager)current).maxConnections = PluginConfig.ServerMaxPlayers;
current3._lobbyPasswordInput.text = PluginConfig.ServerPassword;
current3._lobbyTypeDropdown.value = (int)PluginConfig.ServerType;
current3._hostLobbyRealm = PluginConfig.ServerTag;
current._bannedClientList.Clear();
current._mutedClientList.Clear();
if (hostSettingsProfile._banList != null)
{
current._bannedClientList.AddRange(hostSettingsProfile._banList);
}
if (hostSettingsProfile._mutedList != null)
{
current._mutedClientList.AddRange(hostSettingsProfile._mutedList);
}
SteamLobbyType serverType = PluginConfig.ServerType;
if (1 == 0)
{
}
ELobbyType val = (ELobbyType)(serverType switch
{
SteamLobbyType.PUBLIC => 2,
SteamLobbyType.FRIENDS => 1,
SteamLobbyType.PRIVATE => 0,
_ => 2,
});
if (1 == 0)
{
}
ELobbyType val2 = val;
int num = PluginConfig.CharacterSlotToUse;
if (0 > num || num > current2._characterFiles.Length)
{
Plugin.Logger.LogWarning((object)$"Save slot {num} is invalid! Valid slots are between 0 and {current2._characterFiles.Length}. Defaulting to 0.");
num = 0;
}
if (current2._characterFiles[num]._isEmptySlot)
{
Plugin.Logger.LogWarning((object)$"Slot {num} is empty! Creating a new character in it...");
current2._characterFile = current2._characterFiles[num];
CharacterCreationManager characterCreationManager = ProfileDataManager._current._charSelectManager._characterCreationManager;
characterCreationManager.SelectRace(0);
characterCreationManager.RandomizeAll();
characterCreationManager._characterNameInputField.text = "Hostman";
characterCreationManager.Create_Character();
}
current2._characterFile = current2._characterFiles[num];
SteamLobby._current.HostLobby(val2);
MainMenuManager._current._characterSelectManager.Send_CharacterFile();
}
private void LogServerConfig()
{
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
bool periodicRestartEnabled = PluginConfig.PeriodicRestartEnabled;
int periodicRestartIntervalSeconds = PluginConfig.PeriodicRestartIntervalSeconds;
Action<object> action = Plugin.Logger.LogInfo;
int periodicRestartPlayerThresholdPercent = PluginConfig.PeriodicRestartPlayerThresholdPercent;
int periodicRestartPlayerThreshold = PluginConfig.PeriodicRestartPlayerThreshold;
action("=== Server Configuration ===");
action("Server Name : " + PluginConfig.ServerName);
action($"Server Type : {PluginConfig.ServerType}");
action($"Server Tag : {PluginConfig.ServerTag}");
action("Server Password : " + (string.IsNullOrEmpty(PluginConfig.ServerPassword) ? "[None]" : PluginConfig.ServerPassword));
action("Server MOTD : " + (string.IsNullOrEmpty(PluginConfig.ServerMOTD) ? "[None]" : PluginConfig.ServerMOTD));
action($"Max Players : {PluginConfig.ServerMaxPlayers}");
action("Auto Restart : " + ((!periodicRestartEnabled) ? "disabled" : (Utils.FormatInterval(periodicRestartIntervalSeconds) + ((periodicRestartPlayerThresholdPercent == 100) ? "" : $" at {periodicRestartPlayerThreshold} players left ({periodicRestartPlayerThresholdPercent}%)"))));
action("============================");
}
}
public enum SteamLobbyType : byte
{
PUBLIC,
FRIENDS,
PRIVATE
}
public static class Utils
{
public static bool TryParseInterval(string text, out int seconds)
{
if (string.IsNullOrWhiteSpace(text))
{
seconds = 0;
return false;
}
Match match = Regex.Match(text, "^\\s*(?:([0-9]+)d)?\\s*(?:([0-9]+)h)?\\s*(?:([0-9]+)m)?\\s*(?:([0-9]+)s)?\\s*$");
bool success = match.Groups[1].Success;
bool success2 = match.Groups[2].Success;
bool success3 = match.Groups[3].Success;
bool success4 = match.Groups[4].Success;
seconds = 0;
if (!match.Success || !(success || success2 || success3 || success4))
{
return false;
}
seconds += (success ? (int.Parse(match.Groups[1].Value) * 86400) : 0);
seconds += (success2 ? (int.Parse(match.Groups[2].Value) * 3600) : 0);
seconds += (success3 ? (int.Parse(match.Groups[3].Value) * 60) : 0);
seconds += (success4 ? int.Parse(match.Groups[4].Value) : 0);
return true;
}
public static string FormatInterval(int seconds, bool pretty = false)
{
if (seconds == 0)
{
return pretty ? "0 second(s)" : "0s";
}
int num = seconds / 86400;
seconds %= 86400;
int num2 = seconds / 3600;
seconds %= 3600;
int num3 = seconds / 60;
seconds %= 60;
string text = "";
if (num != 0)
{
text += (pretty ? $"{num} day(s)" : $"{num}d");
}
if (pretty && num != 0 && num2 != 0)
{
text += ", ";
}
if (num2 != 0)
{
text += (pretty ? $"{num2} hour(s)" : $"{num2}h");
}
if (pretty && num2 != 0 && num3 != 0)
{
text += ", ";
}
if (num3 != 0)
{
text += (pretty ? $"{num3} minute(s)" : $"{num3}m");
}
if (pretty && num3 != 0 && seconds != 0)
{
text += ", ";
}
if (seconds != 0)
{
text += (pretty ? $"{seconds} second(s)" : $"{seconds}s");
}
return text;
}
}
public static class WineDetect
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate IntPtr WineGetVersion();
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate void WineGetHostVersion(out string sysName, out string version);
private static bool _checkDone = false;
private static bool _isRunningInWine = false;
private static string _systemName = "";
private static string _systemVersion = "";
private static string _wineVersion = "";
public static bool IsRunningInWine
{
get
{
Check();
return _isRunningInWine;
}
}
public static string SystemName
{
get
{
Check();
return _systemName;
}
}
public static string SystemVersion
{
get
{
Check();
return _systemVersion;
}
}
public static string WineVersion
{
get
{
Check();
return _wineVersion;
}
}
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern IntPtr GetModuleHandleA(string moduleName);
[DllImport("Kernel32.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr module, string procName);
public static void Check()
{
if (_checkDone)
{
return;
}
_checkDone = true;
IntPtr moduleHandleA = GetModuleHandleA("ntdll.dll");
if (!(moduleHandleA == IntPtr.Zero))
{
IntPtr procAddress = GetProcAddress(moduleHandleA, "wine_get_version");
IntPtr procAddress2 = GetProcAddress(moduleHandleA, "wine_get_host_version");
if (!(procAddress == IntPtr.Zero) && !(procAddress2 == IntPtr.Zero))
{
IntPtr ptr = Marshal.GetDelegateForFunctionPointer<WineGetVersion>(procAddress)();
string wineVersion = Marshal.PtrToStringAnsi(ptr);
Marshal.GetDelegateForFunctionPointer<WineGetHostVersion>(procAddress2)(out var sysName, out var version);
_isRunningInWine = true;
_systemName = sysName;
_systemVersion = version;
_wineVersion = wineVersion;
}
}
}
}
internal static class ModInfo
{
public const string GUID = "FleesDedicatedServer";
public const string NAME = "DedicatedServer";
public const string VERSION = "0.1.0";
}
}
namespace AtlyssDedicatedServer.HarmonyPatches
{
[HarmonyPatch(typeof(HostConsole), "Send_ServerMessage")]
[HarmonyPriority(800)]
internal static class ChatManagerPatch
{
private static bool Prefix(ref string _message)
{
if (string.IsNullOrWhiteSpace(_message))
{
return false;
}
string[] array = _message.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (_message.Contains('<') || _message.Contains('>'))
{
Plugin.Logger.LogInfo((object)"'<' and '>' are not allowed in server messages.");
return false;
}
if (_message[0] != '/')
{
HostConsole._current.Init_ServerMessage(_message);
return false;
}
if (array[0].Trim() == "/restart")
{
if (array.Length < 2 || !Utils.TryParseInterval(array[1], out var seconds) || seconds < 1)
{
seconds = 20;
}
Plugin.Handler.ScheduleRestart(seconds);
return false;
}
if (array[0].Trim() == "/shutdown")
{
if (array.Length < 2 || !Utils.TryParseInterval(array[1], out var seconds2) || seconds2 < 1)
{
seconds2 = 20;
}
Plugin.Handler.ScheduleShutdown(seconds2);
return false;
}
if (_message.Trim() == "/cancelsd" || _message.Trim() == "/cancelrt")
{
Plugin.Handler.CancelShutdownOrRestart();
return false;
}
HostConsole._current._cmdManager.Init_ConsoleCommand(array[0].TrimStart('/'), (array.Length > 1) ? array[1] : string.Empty);
return false;
}
}
[HarmonyPatch(typeof(ChatBehaviour), "New_ChatMessage")]
internal static class ChatMirrorPatch
{
private static void Postfix(string _message)
{
string text = StripUnityRichText(_message);
if (!(text == HostConsoleFixPatch.LastServerMessage) || !((DateTime.UtcNow - HostConsoleFixPatch.LastServerMessageTime).TotalMilliseconds < 100.0))
{
Logger.LogInfo((object)("[Chat] " + text));
}
}
private static string StripUnityRichText(string input)
{
return Regex.Replace(input, "<.*?>", string.Empty);
}
}
[HarmonyPatch(typeof(AtlyssNetworkManager), "Clear_ConsoleInit")]
internal static class ClearPatch
{
private static bool Prefix()
{
return false;
}
}
[HarmonyPatch(typeof(AtlyssNetworkManager), "Console_GetInput")]
internal static class ConsolePatch
{
private static bool Prefix()
{
Plugin.ConsoleListener.ProcessInput();
return false;
}
}
[HarmonyPatch(typeof(HostConsole), "New_LogMessage")]
internal class HostConsoleFixPatch
{
internal static string LastServerMessage { get; private set; } = "";
internal static DateTime LastServerMessageTime { get; private set; }
private static bool Prefix(string _message)
{
string value = $"[{DateTime.Now.Hour}:{DateTime.Now.Minute}] " + _message;
LastServerMessage = _message;
LastServerMessageTime = DateTime.UtcNow;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(value);
Console.ResetColor();
return false;
}
}
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
internal static class PreventAudioChanges
{
internal static bool LockAudio { get; set; }
private static bool Prefix()
{
return !LockAudio;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}