using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using Alpha.Core.Command;
using Alpha.Core.Commands;
using Alpha.Core.Util;
using Alpha.Patches;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PurrNet;
using Steamworks;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AndrewLin")]
[assembly: AssemblyConfiguration("Publish")]
[assembly: AssemblyDescription("Alpha: A mod for On-Together to provide common utilities and features.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0+587928ff6442b995d7585cea51766753af75276d")]
[assembly: AssemblyProduct("AndrewLin.OnTogether.Alpha")]
[assembly: AssemblyTitle("AndrewLin.OnTogether.Alpha")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/andrewlimforfun/ot-mods")]
[assembly: AssemblyVersion("0.1.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 Alpha
{
[BepInPlugin("com.andrewlin.ontogether.alpha", "Alpha", "0.1.0")]
public class AlphaPlugin : BaseUnityPlugin
{
private static readonly ConcurrentQueue<Action> _mainThreadQueue = new ConcurrentQueue<Action>();
public const string ModGUID = "com.andrewlin.ontogether.alpha";
public const string ModName = "Alpha";
public const string ModVersion = "0.1.0";
public static ConfigEntry<bool>? EnableFeature { get; private set; }
public static ConfigEntry<bool>? ShowCommand { get; private set; }
public static ConfigEntry<bool>? TimestampLog { get; private set; }
public static ConfigEntry<bool>? SuppressPurrNetNullRef { get; private set; }
public static ChatCommandManager? CommandManager { get; private set; }
public static void RunOnMainThread(Action action)
{
_mainThreadQueue.Enqueue(action);
}
private void Awake()
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
InitConfig();
if (TimestampLog.Value)
{
TimestampLogListener.Install();
}
TimestampLogListener.SuppressPurrNetNullRef = SuppressPurrNetNullRef.Value;
((BaseUnityPlugin)this).Logger.LogInfo((object)"Alpha v0.1.0 is loaded!");
Harmony val = new Harmony("com.andrewlin.ontogether.alpha");
val.PatchAll(typeof(TextChannelManagerPatch));
CommandManager = new ChatCommandManager();
CommandManager.Register(new AlphaMyPositionCommand());
CommandManager.Register(new AlphaWhoIsCommand());
CommandManager.Register(new AlphaServerInfoCommand());
CommandManager.Register(new AlphaAddNotificationCommand());
CommandManager.Register(new AlphaUnloadUnusedAssetsCommand());
}
private void InitConfig()
{
EnableFeature = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableFeature", true, "Enable or disable the mod feature.");
ShowCommand = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ShowCommand", false, "Show the command in chat when used.");
TimestampLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "TimestampLog", true, "Prepend [HH:mm:ss] timestamps to each line in LogOutput.log and the console.");
SuppressPurrNetNullRef = ((BaseUnityPlugin)this).Config.Bind<bool>("Logging", "SuppressPurrNetNullRef", true, "Suppress spammy PurrNet NetworkReflection NullReferenceException lines from LogOutput.log and the console (known PurrNet bug).");
}
private void Update()
{
Action result;
while (_mainThreadQueue.TryDequeue(out result))
{
try
{
result();
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogError((object)("Main thread action failed: " + ex.Message));
}
}
}
private void Start()
{
}
private void OnDestroy()
{
}
}
public static class BuildInfo
{
public const string Version = "0.1.0";
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "AndrewLin.OnTogether.Alpha";
public const string PLUGIN_NAME = "AndrewLin.OnTogether.Alpha";
public const string PLUGIN_VERSION = "0.1.0";
}
}
namespace Alpha.Patches
{
[HarmonyPatch(typeof(TextChannelManager))]
public class TextChannelManagerPatch
{
[HarmonyPatch("OnEnterPressed")]
[HarmonyPrefix]
public static void OnEnterPressedPrefix()
{
string text = MonoSingleton<UIManager>.I.MessageInput.text;
if (!string.IsNullOrEmpty(text) && text.StartsWith('/') && AlphaPlugin.CommandManager != null)
{
bool flag = AlphaPlugin.CommandManager.ProcessInput(text);
ConfigEntry<bool>? showCommand = AlphaPlugin.ShowCommand;
if (showCommand != null && !showCommand.Value && flag)
{
ChatUtils.CleanCommand();
}
}
}
}
}
namespace Alpha.Core.Util
{
public static class ChatUtils
{
private static readonly Regex _commonTMPTagRegex = new Regex("</?(?:color|b|i|u|s|sup|sub|size|alpha|mark|cspace|width|uppercase|lowercase|smallcaps|font|voffset|nobr|noparse|sprite|link|align|rotate|#[0-9a-fA-F]{3,8})[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
public const int MaxMessageLength = 250;
public static void AddGlobalNotification(string text)
{
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
if (!((Object)(object)i == (Object)null))
{
i.AddNotification(text);
}
}
public static void SendMessageAsync(string userName, string text, bool IsLocal = false, string chunkStrategy = "word", Vector3? position = null)
{
string text2 = chunkStrategy.ToLower();
if (1 == 0)
{
}
IStringChunker stringChunker = ((!(text2 == "word")) ? ((IStringChunker)new HardCutChunker()) : ((IStringChunker)new WordBoundaryChunker()));
if (1 == 0)
{
}
IStringChunker stringChunker2 = stringChunker;
foreach (string item in stringChunker2.Chunk(text, 250))
{
SendMessageTruncatedAsync(userName, item, IsLocal, position);
}
}
public static void SendMessageTruncatedAsync(string userName, string text, bool IsLocal = false, Vector3? position = null)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
byte[] bytes = Encoding.Unicode.GetBytes(text.Substring(0, Math.Min(250, text.Length)));
byte[] bytes2 = Encoding.Unicode.GetBytes(userName);
string playerSteamID = SteamUtils.GetPlayerSteamID();
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
Transform mainPlayer = i.MainPlayer;
i.SendMessageAsync(bytes, bytes2, IsLocal, (Vector3)(((??)position) ?? mainPlayer.position), playerSteamID, default(RPCInfo));
}
public static void CleanCommand()
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
LockState lockState = (LockState)(NetworkSingleton<MusicManager>.I.IsActive ? 5 : 0);
MonoSingleton<TaskManager>.I.SetLockState(lockState);
EventSystem.current.SetSelectedGameObject((GameObject)null);
string text = MonoSingleton<UIManager>.I.MessageInput.text;
if (!text.StartsWith("/help"))
{
MonoSingleton<UIManager>.I.MessageInput.text = "";
}
}
public static string CleanTMPTags(string input)
{
return _commonTMPTagRegex.Replace(input, string.Empty);
}
public static void UISendMessage(string text)
{
TMP_InputField messageInput = MonoSingleton<UIManager>.I.MessageInput;
messageInput.text = text;
((UnityEvent<string>)(object)messageInput.onSubmit).Invoke(messageInput.text);
}
}
public class PlayerDetail
{
public readonly string SteamID;
public readonly PlayerID PlayerID;
public readonly PlayerIDInfo PlayerIDInfo;
public readonly NetworkTransform PlayerTransform;
public TextMeshProUGUI UserNameTMP => ((Component)PlayerTransform).GetComponent<PlayerController>().PlayerNameText;
public string UserName => ((TMP_Text)UserNameTMP).text;
public string UserNameClean => ChatUtils.CleanTMPTags(UserName).Trim();
public string SteamPersonaName => SteamUtils.GetSteamPersonaName(SteamID);
public Vector3 Position => ((Component)PlayerTransform).transform.position;
public PlayerDetail(string steamID, PlayerID playerID, PlayerIDInfo playerIDInfo, NetworkTransform playerTransform)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
SteamID = steamID;
PlayerID = playerID;
PlayerIDInfo = playerIDInfo;
PlayerTransform = playerTransform;
}
}
public static class PlayerLists
{
private static ManualLogSource _log = Logger.CreateLogSource("Alpha.PL");
private static readonly HashSet<string> _adminIds = new HashSet<string> { "76561198144499930", "76561198729588983" };
public static bool IsAdmin(string steamId)
{
if (string.IsNullOrEmpty(steamId))
{
return false;
}
return _adminIds.Contains(steamId);
}
}
public static class PlayerUtils
{
private static readonly Regex _digitsRegex = new Regex("^\\d+$", RegexOptions.Compiled);
private static ManualLogSource _log = Logger.CreateLogSource("Alpha.PU");
public static string GetUserName()
{
string userName = NetworkSingleton<TextChannelManager>.I.UserName;
if (string.IsNullOrEmpty(userName))
{
PlayerDetail playerDetail = GetPlayerDetail();
if (playerDetail != null)
{
userName = playerDetail.UserName;
}
}
return userName;
}
public static string GetUserNameNoFormat()
{
return ChatUtils.CleanTMPTags(GetUserName());
}
public static PlayerDetail? GetPlayerDetail()
{
try
{
PlayerDetail playerDetail = null;
TextChannelManager i = NetworkSingleton<TextChannelManager>.I;
PlayerID? playerId = ((i != null) ? ((NetworkIdentity)i).localPlayer : null);
if (playerId.HasValue)
{
playerDetail = FindPlayer(delegate(string _sid, PlayerID _playerId, PlayerIDInfo _info, NetworkTransform _transform)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
PlayerID? val = playerId;
return val.HasValue && _playerId == val.GetValueOrDefault();
});
}
if (playerDetail == null)
{
string playerSteamID = SteamUtils.GetPlayerSteamID();
playerDetail = FindPlayerBySteamID(playerSteamID);
}
if (playerDetail == null)
{
_log.LogWarning((object)"Could not find player detail for local player.");
}
return playerDetail;
}
catch (Exception arg)
{
_log.LogError((object)$"Error getting player ID: {arg}");
return null;
}
}
public static List<PlayerDetail> FindPlayers(Func<string, PlayerID, PlayerIDInfo, NetworkTransform, bool> predicate)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: 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_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
PlayerPanelController i = NetworkSingleton<PlayerPanelController>.I;
if ((Object)(object)i == (Object)null)
{
return new List<PlayerDetail>();
}
List<PlayerDetail> list = new List<PlayerDetail>();
for (int j = 0; j < i.PlayerIDs.Count; j++)
{
string text = i.PlayerSteamIDs[j];
PlayerID val = i.PlayerIDs[j];
PlayerIDInfo val2 = i.IDInfos[j];
NetworkTransform val3 = i.PlayerTransforms[j];
if (predicate(text, val, val2, val3))
{
list.Add(new PlayerDetail(text, val, val2, val3));
}
}
return list;
}
public static PlayerDetail? FindPlayer(Func<string, PlayerID, PlayerIDInfo, NetworkTransform, bool> predicate)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: 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)
PlayerPanelController i = NetworkSingleton<PlayerPanelController>.I;
if ((Object)(object)i == (Object)null)
{
return null;
}
for (int j = 0; j < i.PlayerIDs.Count; j++)
{
string text = i.PlayerSteamIDs[j];
PlayerID val = i.PlayerIDs[j];
PlayerIDInfo val2 = i.IDInfos[j];
NetworkTransform val3 = i.PlayerTransforms[j];
if (predicate(text, val, val2, val3))
{
return new PlayerDetail(text, val, val2, val3);
}
}
return null;
}
public static PlayerDetail? FindPlayerBySteamID(string steamId)
{
string steamId2 = steamId;
return FindPlayer((string _steamId, PlayerID _pid, PlayerIDInfo _info, NetworkTransform _transform) => _steamId == steamId2);
}
public static PlayerDetail? FindPlayerByQuery(string query)
{
string query2 = query;
if (string.IsNullOrWhiteSpace(query2))
{
return null;
}
if (query2.Equals("_host", StringComparison.OrdinalIgnoreCase))
{
return GetHost();
}
return FindPlayer((string _steamId, PlayerID _pid, PlayerIDInfo _info, NetworkTransform _transform) => QueryMatchesPlayer(_steamId, _pid, _info, _transform, query2));
}
public static List<PlayerDetail> FindPlayersByQuery(string query)
{
string query2 = query;
if (string.IsNullOrWhiteSpace(query2))
{
return new List<PlayerDetail>();
}
return FindPlayers((string _steamId, PlayerID _pid, PlayerIDInfo _info, NetworkTransform _transform) => QueryMatchesPlayer(_steamId, _pid, _info, _transform, query2));
}
private static bool QueryMatchesPlayer(string steamId, PlayerID id, PlayerIDInfo info, NetworkTransform transform, string query)
{
if (_digitsRegex.IsMatch(query) && steamId.EndsWith(query))
{
return true;
}
string text = ((TMP_Text)((Component)transform).GetComponent<PlayerController>().PlayerNameText).text;
if (query.Contains("<") && text.StartsWith(query, StringComparison.OrdinalIgnoreCase))
{
return true;
}
string text2 = ChatUtils.CleanTMPTags(text).Trim();
if (text2.Contains(query, StringComparison.OrdinalIgnoreCase))
{
return true;
}
try
{
if (Regex.IsMatch(text2, query, RegexOptions.IgnoreCase))
{
return true;
}
}
catch (ArgumentException)
{
}
string steamPersonaName = SteamUtils.GetSteamPersonaName(steamId);
if (steamPersonaName != null && steamPersonaName.Contains(query, StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
public static PlayerDetail? GetHost()
{
PlayerDetail playerDetail = FindPlayer((string _sid, PlayerID _playerId, PlayerIDInfo _info, NetworkTransform _transform) => ((PlayerID)(ref _playerId)).isServer);
if (playerDetail == null)
{
string hostSteamId = SteamUtils.GetLobbyOwnerSteamID();
playerDetail = FindPlayer((string steamId, PlayerID _pid, PlayerIDInfo _info, NetworkTransform _t) => steamId == hostSteamId);
}
if (playerDetail == null)
{
_log.LogWarning((object)"Could not find host player in PlayerIDs.");
}
return playerDetail;
}
public static List<PlayerDetail> GetAllPlayers()
{
return FindPlayers((string _sid, PlayerID _pid, PlayerIDInfo _info, NetworkTransform _t) => true);
}
public static string GetLobbyCode()
{
return MonoSingleton<MultiplayerManager>.I.LobbyCode;
}
public static string GetLobbyName()
{
return MonoSingleton<MultiplayerManager>.I.LobbyName;
}
public static int GetPlayerCount()
{
return (NetworkSingleton<PlayerPanelController>.I?.IDInfos?.Count).GetValueOrDefault();
}
public static int GetMaxPlayers()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
return MonoSingleton<MultiplayerManager>.I._lobbyManager.CurrentLobby.MaxPlayers;
}
}
public static class SteamUtils
{
public static bool IsSteamID(string value)
{
ulong result;
return value != null && value.Length == 17 && ulong.TryParse(value, out result);
}
public static string GetPlayerSteamID()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
CSteamID steamID = SteamUser.GetSteamID();
return ((object)(CSteamID)(ref steamID)).ToString();
}
public static string GetSteamPersonaName()
{
return SteamFriends.GetPersonaName();
}
public static string GetSteamPersonaName(string steamId)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
return SteamFriends.GetFriendPersonaName(new CSteamID(ulong.Parse(steamId)));
}
public static string GetLobbyOwnerSteamID()
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
string lobbyCode = MonoSingleton<MultiplayerManager>.I.LobbyCode;
CSteamID val = default(CSteamID);
((CSteamID)(ref val))..ctor(ulong.Parse(lobbyCode));
CSteamID lobbyOwner = SteamMatchmaking.GetLobbyOwner(val);
return ((object)(CSteamID)(ref lobbyOwner)).ToString();
}
}
public class HardCutChunker : IStringChunker
{
[CompilerGenerated]
private sealed class <Chunk>d__0 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
{
private int <>1__state;
private string <>2__current;
private int <>l__initialThreadId;
private string text;
public string <>3__text;
private int maxLength;
public int <>3__maxLength;
public HardCutChunker <>4__this;
private int <start>5__1;
string IEnumerator<string>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Chunk>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (string.IsNullOrEmpty(text))
{
return false;
}
<start>5__1 = 0;
break;
case 1:
<>1__state = -1;
<start>5__1 += maxLength;
break;
}
if (<start>5__1 < text.Length)
{
<>2__current = text.Substring(<start>5__1, Math.Min(maxLength, text.Length - <start>5__1));
<>1__state = 1;
return true;
}
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();
}
[DebuggerHidden]
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
<Chunk>d__0 <Chunk>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<Chunk>d__ = this;
}
else
{
<Chunk>d__ = new <Chunk>d__0(0)
{
<>4__this = <>4__this
};
}
<Chunk>d__.text = <>3__text;
<Chunk>d__.maxLength = <>3__maxLength;
return <Chunk>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<string>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<Chunk>d__0))]
public IEnumerable<string> Chunk(string text, int maxLength)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Chunk>d__0(-2)
{
<>4__this = this,
<>3__text = text,
<>3__maxLength = maxLength
};
}
}
public interface IStringChunker
{
IEnumerable<string> Chunk(string text, int maxLength);
}
public class WordBoundaryChunker : IStringChunker
{
[CompilerGenerated]
private sealed class <Chunk>d__0 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IEnumerator, IDisposable
{
private int <>1__state;
private string <>2__current;
private int <>l__initialThreadId;
private string text;
public string <>3__text;
private int maxLength;
public int <>3__maxLength;
public WordBoundaryChunker <>4__this;
private int <start>5__1;
private int <remaining>5__2;
private int <cut>5__3;
string IEnumerator<string>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <Chunk>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
if (string.IsNullOrEmpty(this.text))
{
return false;
}
<start>5__1 = 0;
break;
case 1:
<>1__state = -1;
return false;
case 2:
<>1__state = -1;
<start>5__1 += maxLength;
break;
case 3:
<>1__state = -1;
<start>5__1 = <cut>5__3 + 1;
break;
}
if (<start>5__1 < this.text.Length)
{
<remaining>5__2 = this.text.Length - <start>5__1;
int num;
if (<remaining>5__2 <= maxLength)
{
string text = this.text;
num = <start>5__1;
<>2__current = text.Substring(num, text.Length - num).Trim();
<>1__state = 1;
return true;
}
<cut>5__3 = this.text.LastIndexOf(' ', <start>5__1 + maxLength - 1, maxLength);
if (<cut>5__3 <= <start>5__1)
{
string obj = this.text;
num = <start>5__1;
<>2__current = obj.Substring(num, <start>5__1 + maxLength - num);
<>1__state = 2;
return true;
}
string obj2 = this.text;
num = <start>5__1;
<>2__current = obj2.Substring(num, <cut>5__3 - num).Trim();
<>1__state = 3;
return true;
}
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();
}
[DebuggerHidden]
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
<Chunk>d__0 <Chunk>d__;
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
<Chunk>d__ = this;
}
else
{
<Chunk>d__ = new <Chunk>d__0(0)
{
<>4__this = <>4__this
};
}
<Chunk>d__.text = <>3__text;
<Chunk>d__.maxLength = <>3__maxLength;
return <Chunk>d__;
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<string>)this).GetEnumerator();
}
}
[IteratorStateMachine(typeof(<Chunk>d__0))]
public IEnumerable<string> Chunk(string text, int maxLength)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <Chunk>d__0(-2)
{
<>4__this = this,
<>3__text = text,
<>3__maxLength = maxLength
};
}
}
internal static class TimestampLogListener
{
private sealed class TimestampedDiskLogListener : ILogListener, IDisposable
{
private readonly TextWriter? _writer;
private readonly LogLevel _displayedLogLevel;
internal TimestampedDiskLogListener(TextWriter? writer, LogLevel displayedLogLevel)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
_writer = writer;
_displayedLogLevel = displayedLogLevel;
}
public void LogEvent(object sender, LogEventArgs eventArgs)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Invalid comparison between Unknown and I4
try
{
if (_writer == null || (eventArgs.Level & _displayedLogLevel) == 0)
{
return;
}
if (SuppressPurrNetNullRef)
{
object data = eventArgs.Data;
if (data != null && (data.ToString()?.Contains("PurrNet.NetworkReflection.ObserversRpc_Original_1")).GetValueOrDefault())
{
return;
}
}
_writer.WriteLine(FormatWithTimestamp(eventArgs));
}
catch (ObjectDisposedException)
{
}
catch (Exception ex2)
{
Diag("LogEvent threw: " + ex2.GetType().Name + ": " + ex2.Message);
}
}
public void Dispose()
{
}
}
private const string PurrNetNullRefMarker = "PurrNet.NetworkReflection.ObserversRpc_Original_1";
private static readonly string DiagPath = Path.Combine(Paths.BepInExRootPath, "TimestampLogListener.diag.log");
internal static bool SuppressPurrNetNullRef { get; set; }
private static void Diag(string msg)
{
try
{
File.AppendAllText(DiagPath, $"[{DateTime.Now:HH:mm:ss.fff}] {msg}{Environment.NewLine}");
}
catch
{
}
}
internal static void Install()
{
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
try
{
Diag("Install() begin");
DiskLogListener val = null;
ILogListener[] array = Logger.Listeners.ToArray();
Diag($"Listeners snapshot count: {array.Length}");
ILogListener[] array2 = array;
foreach (ILogListener val2 in array2)
{
Diag(" Found listener: " + ((object)val2).GetType().FullName);
DiskLogListener val3 = (DiskLogListener)(object)((val2 is DiskLogListener) ? val2 : null);
if (val3 != null)
{
val = val3;
}
}
if (val != null)
{
Diag($"DiskLogListener.LogWriter is null: {val.LogWriter == null}");
TextWriter logWriter = val.LogWriter;
LogLevel displayedLogLevel = val.DisplayedLogLevel;
Diag($"DisplayedLogLevel: {displayedLogLevel}");
Logger.Listeners.Remove((ILogListener)(object)val);
Diag($"DiskLogListener removed. Writer still non-null: {logWriter != null}");
Logger.Listeners.Add((ILogListener)(object)new TimestampedDiskLogListener(logWriter, displayedLogLevel));
Diag("TimestampedDiskLogListener added OK");
}
else
{
Diag("No DiskLogListener found - nothing to replace");
}
Diag("Install() complete");
}
catch (Exception ex)
{
Diag("Install() FAILED: " + ex.GetType().Name + ": " + ex.Message);
Diag(ex.StackTrace ?? "(no stack trace)");
}
}
private static string FormatWithTimestamp(LogEventArgs eventArgs)
{
return $"[{DateTime.Now:HH:mm:ss}] {eventArgs}";
}
}
public static class TimeUtils
{
public static bool TryParseDuration(string input, out TimeSpan result)
{
string text = input.ToUpperInvariant();
string s = (text.StartsWith("P") ? text : ("PT" + text));
try
{
result = XmlConvert.ToTimeSpan(s);
return true;
}
catch
{
}
return TimeSpan.TryParse(input, out result);
}
}
public sealed class TokenValidator
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.TV");
private readonly string _secretHash;
public TokenValidator(string secretHash)
{
_secretHash = secretHash;
}
public bool IsValid(string? token)
{
if (string.IsNullOrEmpty(_secretHash))
{
return true;
}
if (string.IsNullOrEmpty(token))
{
_log.LogWarning((object)"Token is null or empty.");
return false;
}
using SHA256 sHA = SHA256.Create();
byte[] array = sHA.ComputeHash(Encoding.UTF8.GetBytes(token));
string text = BitConverter.ToString(array).Replace("-", "").ToLower();
bool flag = text == _secretHash;
if (!flag)
{
_log.LogWarning((object)("Invalid token. Computed hash: " + text + " does not match expected hash."));
}
else
{
_log.LogInfo((object)"Token is valid.");
}
return flag;
}
}
}
namespace Alpha.Core.Command
{
public class ChatCommandArgs
{
public static readonly ChatCommandArgs EMPTY = new ChatCommandArgs("", new string[0]);
public string Name { get; }
public string[] Args { get; }
public ChatCommandArgs(string name, string[] args)
{
Name = name;
Args = args;
}
public static bool TryParse(string input, out ChatCommandArgs result)
{
if (string.IsNullOrWhiteSpace(input) || !input.StartsWith('/'))
{
result = EMPTY;
return false;
}
string text = input.Trim();
string[] array = text.Substring(1, text.Length - 1).Split(' ', StringSplitOptions.RemoveEmptyEntries);
string name = array[0].ToLower();
string[] args = array.Skip(1).ToArray();
result = new ChatCommandArgs(name, args);
return true;
}
public override string ToString()
{
return "/" + Name + " " + string.Join(' ', Args);
}
}
public class ChatCommandManager
{
private readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.CM");
private readonly Dictionary<string, IChatCommand> _commands = new Dictionary<string, IChatCommand>();
private readonly Dictionary<string, List<IChatCommand>> _byNamespace = new Dictionary<string, List<IChatCommand>>();
public void Register(IChatCommand? command)
{
if (command == null || string.IsNullOrWhiteSpace(command.Name))
{
_log.LogWarning((object)("Attempted to register null or nameless command: " + (command?.GetType().Name ?? "null")));
return;
}
_commands[command.Name] = command;
if (!string.IsNullOrWhiteSpace(command.ShortName))
{
_commands[command.ShortName] = command;
}
string text = command.Namespace ?? "";
if (!string.IsNullOrWhiteSpace(text))
{
if (!_byNamespace.TryGetValue(text, out List<IChatCommand> value))
{
value = new List<IChatCommand>();
_byNamespace[text] = value;
NamespaceHelpCommand namespaceHelpCommand = new NamespaceHelpCommand(text, value);
_commands[namespaceHelpCommand.Name] = namespaceHelpCommand;
if (!string.IsNullOrWhiteSpace(namespaceHelpCommand.ShortName) && !_commands.ContainsKey(namespaceHelpCommand.ShortName))
{
_commands[namespaceHelpCommand.ShortName] = namespaceHelpCommand;
}
_log.LogInfo((object)("Auto-registered help: /" + namespaceHelpCommand.Name + " (/" + namespaceHelpCommand.ShortName + ")"));
}
if (!value.Contains(command))
{
value.Add(command);
}
}
string text2 = (string.IsNullOrWhiteSpace(command.ShortName) ? "" : (" (/" + command.ShortName + ")"));
_log.LogInfo((object)("Registered command: /" + command.Name + text2 + " [" + text + "]"));
}
public bool ContainsCommand(string commandName)
{
return _commands.ContainsKey(commandName);
}
public IEnumerable<IChatCommand> GetAllCommands()
{
return _commands.Values.Distinct();
}
public bool ProcessInput(string input)
{
if (!ChatCommandArgs.TryParse(input, out ChatCommandArgs result))
{
return false;
}
if (_commands.TryGetValue(result.Name, out IChatCommand value))
{
_log.LogInfo((object)$"Executing command: {result}");
try
{
value.Execute(result.Args);
}
catch (Exception ex)
{
ChatUtils.AddGlobalNotification($"Error executing '{result}': {ex.Message}");
}
return true;
}
return false;
}
}
public interface IChatCommand : IComparable<IChatCommand>
{
string Name { get; }
string ShortName => "";
string Description { get; }
string Namespace { get; }
bool IsHidden => false;
void Execute(string[] args);
new string ToString()
{
return Name;
}
int IComparable<IChatCommand>.CompareTo(IChatCommand? other)
{
if (other == null)
{
return 1;
}
return string.Compare(Name, other.Name, StringComparison.Ordinal);
}
}
internal class NamespaceHelpCommand : IChatCommand, IComparable<IChatCommand>
{
private readonly string _namespace;
private readonly List<IChatCommand> _commands;
public string Name => _namespace + "help";
public string ShortName => (_namespace.Length >= 1) ? (_namespace.Substring(0, 1) + "h") : "";
public string Description => "Lists all " + _namespace + " commands.";
public string Namespace => "";
public NamespaceHelpCommand(string ns, List<IChatCommand> commands)
{
_namespace = ns;
_commands = commands;
}
public void Execute(string[] args)
{
SortedSet<IChatCommand> sortedSet = new SortedSet<IChatCommand>(_commands);
bool flag = args.Length == 1 && (args[0].ToLower() == "verbose" || args[0].ToLower() == "v");
bool flag2 = args.Length == 1 && !flag;
if (args.Length == 0 || flag)
{
StringBuilder stringBuilder = new StringBuilder("/" + _namespace + "help - available commands:");
foreach (IChatCommand item in sortedSet)
{
if (!item.IsHidden)
{
string text = (string.IsNullOrWhiteSpace(item.ShortName) ? "" : (" (/" + item.ShortName + ")"));
string text2 = (flag ? (": " + item.Description) : "");
stringBuilder.Append("\n/" + item.Name + text + text2);
}
}
ChatUtils.AddGlobalNotification(stringBuilder.ToString());
}
else if (flag2)
{
string needle = args[0].ToLower();
IChatCommand chatCommand = sortedSet.FirstOrDefault((IChatCommand c) => c.Name == needle || c.ShortName == needle);
if (chatCommand != null)
{
string text3 = (string.IsNullOrWhiteSpace(chatCommand.ShortName) ? "" : (" (/" + chatCommand.ShortName + ")"));
ChatUtils.AddGlobalNotification("/" + chatCommand.Name + text3 + ": " + chatCommand.Description);
}
else
{
ChatUtils.AddGlobalNotification("Unknown command '" + needle + "'. Type /" + _namespace + "help for a list.");
}
}
}
}
}
namespace Alpha.Core.Commands
{
public class AlphaAddNotificationCommand : IChatCommand, IComparable<IChatCommand>
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.AANPC");
public string Name => "alphaaddnotification";
public string ShortName => "aan";
public string Description => "Add a notification. Usage: /alphaaddnotification [message]";
public string Namespace => "alpha";
public void Execute(string[] args)
{
if (args.Length == 0)
{
ChatUtils.AddGlobalNotification("Usage: /alphaaddnotification [message]");
return;
}
string text = string.Join(" ", args).Trim();
_log.LogInfo((object)("Adding notification: " + text));
ChatUtils.AddGlobalNotification(text);
}
}
public class AlphaMyPositionCommand : IChatCommand, IComparable<IChatCommand>
{
public string Name => "alphamyposition";
public string ShortName => "amp";
public string Description => "Show your current position. Usage: /alphamyposition";
public string Namespace => "alpha";
public void Execute(string[] args)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = PlayerUtils.GetPlayerDetail()?.Position ?? Vector3.zero;
ChatUtils.AddGlobalNotification($"Your current position: {val}");
}
}
public class AlphaQuitCommand : IChatCommand, IComparable<IChatCommand>
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.AQC");
public string Name => "alphaquit";
public string ShortName => "aq";
public string Description => "Quit the game. Usage: /alphaquit";
public string Namespace => "alpha";
public bool IsHidden => true;
public void Execute(string[] args)
{
_log.LogWarning((object)"Quitting game via /alphaquit command.");
Application.Quit();
}
}
public class AlphaServerInfoCommand : IChatCommand, IComparable<IChatCommand>
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.ASIC");
public string Name => "alphaserverinfo";
public string ShortName => "asi";
public string Description => "Show server information. Usage: /alphaserverinfo";
public string Namespace => "alpha";
public void Execute(string[] args)
{
PlayerDetail host = PlayerUtils.GetHost();
ChatUtils.AddGlobalNotification("Lobby Name: " + PlayerUtils.GetLobbyName() + "\nLobby Code: " + PlayerUtils.GetLobbyCode() + "\n" + $"Player Count: {PlayerUtils.GetPlayerCount()}/{PlayerUtils.GetMaxPlayers()}\n" + "Host: " + host?.UserName + " (Steam: " + host?.SteamPersonaName + ")");
}
}
public class AlphaUnloadUnusedAssetsCommand : IChatCommand, IComparable<IChatCommand>
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.AUUA");
public string Name => "alphaunloadunusedassets";
public string ShortName => "auua";
public string Description => "Unload unused Unity assets. Usage: /alphaunloadunusedassets";
public string Namespace => "alpha";
public void Execute(string[] args)
{
_log.LogInfo((object)"Unloading unused assets via /alphaunloadunusedassets command.");
ChatUtils.AddGlobalNotification("Unloading unused assets...");
Resources.UnloadUnusedAssets();
}
}
public class AlphaWhoIsCommand : IChatCommand, IComparable<IChatCommand>
{
private static readonly ManualLogSource _log = Logger.CreateLogSource("Alpha.AWIC");
public string Name => "alphawhois";
public string ShortName => "awi";
public string Description => "Show information about a player. Usage: /alphawhois [player]";
public string Namespace => "alpha";
public void Execute(string[] args)
{
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
if (args.Length == 0)
{
ChatUtils.AddGlobalNotification("Usage: /alphawhois [player]");
return;
}
string text = string.Join(" ", args).Trim();
List<PlayerDetail> list = PlayerUtils.FindPlayersByQuery(text);
if (list.Count == 0)
{
ChatUtils.AddGlobalNotification("No players found matching \"" + text + "\".");
return;
}
_log.LogInfo((object)$"Found {list.Count} player(s) matching \"{text}\":");
ChatUtils.AddGlobalNotification($"Found {list.Count} player(s) matching \"{text}\":");
foreach (PlayerDetail item in list)
{
string text2 = ChatUtils.CleanTMPTags(item.UserName).Trim();
string text3 = item.SteamPersonaName ?? "?";
Vector3 val = PlayerUtils.GetPlayerDetail()?.Position ?? Vector3.zero;
int num = (int)Vector3.Distance(item.Position, val);
string text4 = $"{text2} | {text3} | {item.SteamID} | {item.Position} ({num})";
_log.LogInfo((object)text4);
ChatUtils.AddGlobalNotification(text4);
}
}
}
}