using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using Fleck2;
using Fleck2.Handlers;
using Fleck2.Interfaces;
using H3Status.Model;
using H3Status.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using Valve.Newtonsoft.Json;
using Valve.Newtonsoft.Json.Converters;
using Valve.Newtonsoft.Json.Serialization;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("H3Status")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.5.1.0")]
[assembly: AssemblyInformationalVersion("0.5.1+6a5e0dc5f46c295da8d6b5979e4a299739236a95")]
[assembly: AssemblyProduct("H3Status")]
[assembly: AssemblyTitle("H3Status")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.5.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
internal sealed class IsReadOnlyAttribute : Attribute
{
}
[CompilerGenerated]
[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]
[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]
[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 xyz.bacur.plugins
{
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "H3Status";
public const string PLUGIN_NAME = "H3Status";
public const string PLUGIN_VERSION = "0.5.1";
}
}
namespace Fleck2
{
public static class Fleck2Extensions
{
public delegate void Action();
public delegate void Action<in T>(T t);
public delegate void Action<in T, in TU>(T t, TU u);
public delegate void Action<in T, in TU, in TV>(T t, TU u, TV v);
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T, out TResult>(T t);
public delegate TResult Func<in T, in TU, out TResult>(T t, TU u);
public delegate TResult Func<in T, in TU, in TV, out TResult>(T t, TU u, TV v);
public static T[] ToArray<T>(this IEnumerable<T> enumerable)
{
return enumerable.ToList().ToArray();
}
public static List<T> ToList<T>(this IEnumerable<T> enumerable)
{
List<T> list = new List<T>();
foreach (T item in enumerable)
{
list.Add(item);
}
return list;
}
public static IEnumerable<T> Skip<T>(this IEnumerable<T> enumerable, int count)
{
foreach (T item in enumerable)
{
if (count-- <= 0)
{
yield return item;
}
}
}
public static byte[] Skip(this byte[] array, int count)
{
byte[] array2 = new byte[array.Length - count];
int num = 0;
for (int i = 0; i < array.Length; i++)
{
if (count-- <= 0)
{
array2[num] = array[i];
num++;
}
}
return array2;
}
public static IEnumerable<T> Take<T>(this IEnumerable<T> enumerable, int count)
{
foreach (T item in enumerable)
{
if (count-- > 0)
{
yield return item;
continue;
}
yield break;
}
}
public static IEnumerable<T> Skip<T>(this T[] enumerable, int count)
{
foreach (T val in enumerable)
{
if (count-- > 0)
{
yield return val;
continue;
}
break;
}
}
public static IEnumerable<T> Take<T>(this T[] enumerable, int count)
{
foreach (T val in enumerable)
{
if (count-- > 0)
{
yield return val;
continue;
}
break;
}
}
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> enumerable, Converter<TSource, TResult> selector)
{
foreach (TResult item in enumerable.ToList().ConvertAll(selector))
{
yield return item;
}
}
}
public enum LogLevel
{
None,
Debug,
Info,
Warn,
Error
}
public class FleckLog
{
public static LogLevel Level = LogLevel.Info;
public static Fleck2Extensions.Action<LogLevel, string, Exception> LogAction = delegate(LogLevel level, string message, Exception ex)
{
if (Level != LogLevel.None && level >= Level)
{
Console.WriteLine("{0} [{1}] {2} {3}", DateTime.Now, level, message, ex);
}
};
public static void Warn(string message, Exception ex = null)
{
LogAction(LogLevel.Warn, message, ex);
}
public static void Error(string message, Exception ex = null)
{
LogAction(LogLevel.Error, message, ex);
}
public static void Debug(string message, Exception ex = null)
{
LogAction(LogLevel.Debug, message, ex);
}
public static void Info(string message, Exception ex = null)
{
LogAction(LogLevel.Info, message, ex);
}
}
public enum FrameType : byte
{
Continuation = 0,
Text = 1,
Binary = 2,
Close = 8,
Ping = 9,
Pong = 10
}
public class HandlerFactory
{
public static IHandler BuildHandler(WebSocketHttpRequest request, Action<string> onMessage, Fleck2Extensions.Action onClose, Action<byte[]> onBinary)
{
switch (GetVersion(request))
{
case "76":
return Draft76Handler.Create(request, onMessage);
case "7":
case "8":
case "13":
return Hybi13Handler.Create(request, onMessage, onClose, onBinary);
default:
throw new WebSocketException(1003);
}
}
public static string GetVersion(WebSocketHttpRequest request)
{
if (request.Headers.TryGetValue("Sec-WebSocket-Version", out var value))
{
return value;
}
if (request.Headers.TryGetValue("Sec-WebSocket-Draft", out value))
{
return value;
}
if (request.Headers.ContainsKey("Sec-WebSocket-Key1"))
{
return "76";
}
return "75";
}
}
public class HandshakeException : Exception
{
public HandshakeException()
{
}
public HandshakeException(string message)
: base(message)
{
}
public HandshakeException(string message, Exception innerException)
: base(message, innerException)
{
}
}
public static class IntExtensions
{
public static byte[] ToBigEndianBytes<T>(this int source)
{
Type typeFromHandle = typeof(T);
byte[] bytes;
if ((object)typeFromHandle == typeof(ushort))
{
bytes = BitConverter.GetBytes((ushort)source);
}
else if ((object)typeFromHandle == typeof(ulong))
{
bytes = BitConverter.GetBytes((ulong)source);
}
else
{
if ((object)typeFromHandle != typeof(int))
{
throw new InvalidCastException("Cannot be cast to T");
}
bytes = BitConverter.GetBytes(source);
}
if (BitConverter.IsLittleEndian)
{
Array.Reverse((Array)bytes);
}
return bytes;
}
public static int ToLittleEndianInt(this byte[] source)
{
if (BitConverter.IsLittleEndian)
{
Array.Reverse((Array)source);
}
if (source.Length == 2)
{
return BitConverter.ToUInt16(source, 0);
}
if (source.Length == 8)
{
return (int)BitConverter.ToUInt64(source, 0);
}
throw new ArgumentException("Unsupported Size");
}
}
public class ReadState
{
public List<byte> Data { get; private set; }
public FrameType? FrameType { get; set; }
public ReadState()
{
Data = new List<byte>();
}
public void Clear()
{
Data.Clear();
FrameType = null;
}
}
public class RequestParser
{
private const string Pattern = "^(?<method>[^\\s]+)\\s(?<path>[^\\s]+)\\sHTTP\\/1\\.1\\r\\n((?<field_name>[^:\\r\\n]+):\\s(?<field_value>[^\\r\\n]+)\\r\\n)+\\r\\n(?<body>.+)?";
private static readonly Regex Regex = new Regex("^(?<method>[^\\s]+)\\s(?<path>[^\\s]+)\\sHTTP\\/1\\.1\\r\\n((?<field_name>[^:\\r\\n]+):\\s(?<field_value>[^\\r\\n]+)\\r\\n)+\\r\\n(?<body>.+)?", RegexOptions.IgnoreCase);
public static WebSocketHttpRequest Parse(byte[] bytes)
{
return Parse(bytes, "ws");
}
public static WebSocketHttpRequest Parse(byte[] bytes, string scheme)
{
string input = Encoding.UTF8.GetString(bytes);
Match match = Regex.Match(input);
if (!match.Success)
{
return null;
}
WebSocketHttpRequest webSocketHttpRequest = new WebSocketHttpRequest
{
Method = match.Groups["method"].Value,
Path = match.Groups["path"].Value,
Body = match.Groups["body"].Value,
Bytes = bytes,
Scheme = scheme
};
CaptureCollection captures = match.Groups["field_name"].Captures;
CaptureCollection captures2 = match.Groups["field_value"].Captures;
for (int i = 0; i < captures.Count; i++)
{
string key = captures[i].ToString();
string value = captures2[i].ToString();
webSocketHttpRequest.Headers[key] = value;
}
return webSocketHttpRequest;
}
}
public class SocketCancellationToken : ICancellationToken
{
private readonly object _syncLock = new object();
public readonly Guid Token;
private bool _isCancellationRequested;
public bool IsCancellationRequested
{
get
{
Monitor.Enter(_syncLock);
try
{
return _isCancellationRequested;
}
finally
{
Monitor.Exit(_syncLock);
}
}
private set
{
Monitor.Enter(_syncLock);
try
{
_isCancellationRequested = value;
}
finally
{
Monitor.Exit(_syncLock);
}
}
}
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested)
{
throw new SocketCancellationTokenException(this);
}
}
public void Cancel()
{
IsCancellationRequested = true;
}
}
public class SocketCancellationTokenException : Exception
{
public SocketCancellationToken Token { get; private set; }
public SocketCancellationTokenException(SocketCancellationToken token)
{
Token = token;
}
}
public class SocketFactory
{
public SocketCancellationToken Token { get; private set; }
public SocketFactory(SocketCancellationToken token)
{
Token = token;
}
public void HandleAsync<TResult>(Fleck2Extensions.Func<AsyncCallback, object, IAsyncResult> beginMethod, Fleck2Extensions.Func<IAsyncResult, TResult> endMethod, Action<SocketResult> resultCallback)
{
DoAsyncTask(delegate
{
beginMethod(delegate(IAsyncResult result)
{
DoAsyncTask(delegate
{
resultCallback(new SocketResult(endMethod(result)));
}, resultCallback);
}, null);
}, resultCallback);
}
public void HandleAsync(Fleck2Extensions.Func<AsyncCallback, object, IAsyncResult> beginMethod, Fleck2Extensions.Func<IAsyncResult, ICancellationToken, ISocket> endMethod, Action<SocketResult> resultCallback)
{
DoAsyncTask(delegate
{
beginMethod(delegate(IAsyncResult result)
{
DoAsyncTask(delegate
{
resultCallback(new SocketResult(endMethod(result, Token)));
}, resultCallback);
}, null);
}, resultCallback);
}
public void HandleAsyncVoid<T>(Fleck2Extensions.Func<AsyncCallback, object, T> beginMethod, Fleck2Extensions.Action<T> endMethod, Action<SocketResult> resultCallback)
{
DoAsyncTask(delegate
{
beginMethod(delegate(IAsyncResult result)
{
DoAsyncTask(delegate
{
endMethod((T)result);
resultCallback(new SocketResult(true));
}, resultCallback);
}, null);
}, resultCallback);
}
private static void DoAsyncTask(Fleck2Extensions.Action unitOfWork, Action<SocketResult> resultCallback)
{
ThreadPool.QueueUserWorkItem(delegate
{
try
{
unitOfWork();
}
catch (SocketCancellationTokenException)
{
}
catch (Exception result)
{
resultCallback(new SocketResult(result));
}
});
}
}
public class SocketResult
{
private readonly object _result;
public SocketResult(object result)
{
_result = result;
}
public SocketResult Success<TResult>(Fleck2Extensions.Action<TResult> callback)
{
if (!(_result is Exception))
{
callback((TResult)_result);
}
return this;
}
public SocketResult Error<TResult>(Fleck2Extensions.Action<TResult> callback)
{
if (_result is Exception)
{
callback((TResult)_result);
}
return this;
}
public SocketResult Success(Fleck2Extensions.Action callback)
{
if (!(_result is Exception))
{
callback();
}
return this;
}
public TResult AsValue<TResult>()
{
return (TResult)_result;
}
}
public class SocketWrapper : ISocket
{
private readonly Socket _socket;
private Stream _stream;
private readonly SocketCancellationToken _socketCancellationToken;
private readonly SocketFactory _socketFactory;
public string RemoteIpAddress
{
get
{
if (!(_socket.RemoteEndPoint is IPEndPoint iPEndPoint))
{
return null;
}
return iPEndPoint.Address.ToString();
}
}
public int RemotePort
{
get
{
if (!(_socket.RemoteEndPoint is IPEndPoint iPEndPoint))
{
return -1;
}
return iPEndPoint.Port;
}
}
public bool Connected => _socket.Connected;
public Stream Stream => _stream;
public bool NoDelay
{
get
{
return _socket.NoDelay;
}
set
{
_socket.NoDelay = value;
}
}
public SocketWrapper(Socket socket)
{
_socketCancellationToken = new SocketCancellationToken();
_socketFactory = new SocketFactory(_socketCancellationToken);
_socket = socket;
if (_socket.Connected)
{
_stream = new NetworkStream(_socket);
}
}
public void Authenticate(X509Certificate2 certificate, Fleck2Extensions.Action callback, Fleck2Extensions.Action<Exception> error)
{
SslStream ssl = new SslStream(_stream, leaveInnerStreamOpen: false);
_stream = ssl;
Fleck2Extensions.Func<AsyncCallback, object, IAsyncResult> beginMethod = (AsyncCallback cb, object s) => ssl.BeginAuthenticateAsServer(certificate, clientCertificateRequired: false, SslProtocols.Tls, checkCertificateRevocation: false, cb, s);
_socketFactory.HandleAsyncVoid(beginMethod, ssl.EndAuthenticateAsServer, delegate(SocketResult result)
{
result.Success(callback);
result.Error(error);
});
}
public void Listen(int backlog)
{
_socket.Listen(backlog);
}
public void Bind(EndPoint endPoint)
{
_socket.Bind(endPoint);
}
public void Receive(byte[] buffer, Fleck2Extensions.Action<int> callback, Fleck2Extensions.Action<Exception> error, int offset = 0)
{
Fleck2Extensions.Func<AsyncCallback, object, IAsyncResult> beginMethod = (AsyncCallback cb, object data) => _stream.BeginRead(buffer, offset, buffer.Length, cb, data);
_socketFactory.HandleAsync(beginMethod, _stream.EndRead, delegate(SocketResult result)
{
result.Success(callback);
result.Error(error);
});
}
public void Accept(Fleck2Extensions.Action<ISocket> callback, Fleck2Extensions.Action<Exception> error)
{
Fleck2Extensions.Func<IAsyncResult, ICancellationToken, ISocket> endMethod = delegate(IAsyncResult result, ICancellationToken token)
{
token.ThrowIfCancellationRequested();
return new SocketWrapper(_socket.EndAccept(result));
};
_socketFactory.HandleAsync(_socket.BeginAccept, endMethod, delegate(SocketResult result)
{
result.Success(callback);
result.Error(error);
});
}
public void Dispose()
{
_socketCancellationToken.Cancel();
if (_stream != null)
{
_stream.Dispose();
}
if (_socket != null)
{
_socket.Close();
}
}
public void Close()
{
_socketCancellationToken.Cancel();
if (_stream != null)
{
_stream.Close();
}
if (_socket != null)
{
_socket.Close();
}
}
public int EndSend(IAsyncResult asyncResult)
{
_stream.EndWrite(asyncResult);
return 0;
}
public void Send(byte[] buffer, Fleck2Extensions.Action callback, Fleck2Extensions.Action<Exception> error)
{
Fleck2Extensions.Func<AsyncCallback, object, IAsyncResult> beginMethod = (AsyncCallback cb, object s) => _stream.BeginWrite(buffer, 0, buffer.Length, cb, s);
_socketFactory.HandleAsyncVoid(beginMethod, _stream.EndWrite, delegate(SocketResult result)
{
result.Success(callback);
result.Error(error);
});
}
}
public class WebSocketConnection : IWebSocketConnection
{
private readonly Action<IWebSocketConnection> _initialize;
private readonly Fleck2Extensions.Func<WebSocketHttpRequest, IHandler> _handlerFactory;
private readonly Fleck2Extensions.Func<byte[], WebSocketHttpRequest> _parseRequest;
private bool _closed;
private const int ReadSize = 4096;
public ISocket Socket { get; set; }
public IHandler Handler { get; set; }
public Fleck2Extensions.Action OnOpen { get; set; }
public Fleck2Extensions.Action OnClose { get; set; }
public Action<string> OnMessage { get; set; }
public Action<byte[]> OnBinary { get; set; }
public Action<Exception> OnError { get; set; }
public IWebSocketConnectionInfo ConnectionInfo { get; private set; }
public WebSocketConnection(ISocket socket, Action<IWebSocketConnection> initialize, Fleck2Extensions.Func<byte[], WebSocketHttpRequest> parseRequest, Fleck2Extensions.Func<WebSocketHttpRequest, IHandler> handlerFactory)
{
Socket = socket;
OnOpen = delegate
{
};
OnClose = delegate
{
};
OnMessage = delegate
{
};
OnBinary = delegate
{
};
OnError = delegate
{
};
_initialize = initialize;
_handlerFactory = handlerFactory;
_parseRequest = parseRequest;
}
public void Send(string message)
{
if (Handler == null)
{
throw new InvalidOperationException("Cannot send before handshake");
}
if (_closed || !Socket.Connected)
{
FleckLog.Warn("Data sent after close. Ignoring.");
return;
}
byte[] bytes = Handler.FrameText(message);
SendBytes(bytes);
}
public void Send(byte[] message)
{
if (Handler == null)
{
throw new InvalidOperationException("Cannot send before handshake");
}
if (_closed || !Socket.Connected)
{
FleckLog.Warn("Data sent after close. Ignoring.");
return;
}
byte[] bytes = Handler.FrameBinary(message);
SendBytes(bytes);
}
public void StartReceiving()
{
List<byte> data = new List<byte>(4096);
byte[] buffer = new byte[4096];
Read(data, buffer);
}
public void Close()
{
Close(1000);
}
public void Close(int code)
{
if (Handler == null)
{
CloseSocket();
return;
}
byte[] array = Handler.FrameClose(code);
if (array.Length == 0)
{
CloseSocket();
}
else
{
SendBytes(array, CloseSocket);
}
}
public void CreateHandler(IEnumerable<byte> data)
{
WebSocketHttpRequest webSocketHttpRequest = _parseRequest(data.ToArray());
if (webSocketHttpRequest != null)
{
Handler = _handlerFactory(webSocketHttpRequest);
if (Handler != null)
{
ConnectionInfo = WebSocketConnectionInfo.Create(webSocketHttpRequest, Socket.RemoteIpAddress, Socket.RemotePort);
_initialize(this);
byte[] bytes = Handler.CreateHandshake();
SendBytes(bytes, OnOpen);
}
}
}
private void Read(List<byte> data, byte[] buffer)
{
if (_closed || !Socket.Connected)
{
return;
}
Socket.Receive(buffer, delegate(int r)
{
if (r <= 0)
{
FleckLog.Debug("0 bytes read. Closing.");
CloseSocket();
}
else
{
FleckLog.Debug(r + " bytes read");
byte[] array = buffer.Take(r).ToArray();
if (Handler != null)
{
Handler.Receive(array);
}
else
{
data.AddRange(array);
CreateHandler(data);
}
Read(data, buffer);
}
}, HandleReadError);
}
private void HandleReadError(Exception e)
{
if (e is ObjectDisposedException)
{
FleckLog.Debug("Swallowing ObjectDisposedException", e);
return;
}
OnError(e);
if (e is HandshakeException)
{
FleckLog.Debug("Error while reading", e);
}
else if (e is WebSocketException)
{
FleckLog.Debug("Error while reading", e);
Close(((WebSocketException)e).StatusCode);
}
else if (e is IOException)
{
FleckLog.Debug("Error while reading", e);
Close(1006);
}
else
{
FleckLog.Error("Application Error", e);
Close(1011);
}
}
private void SendBytes(byte[] bytes, Fleck2Extensions.Action callback = null)
{
Socket.Send(bytes, delegate
{
FleckLog.Debug("Sent " + bytes.Length + " bytes");
if (callback != null)
{
callback();
}
}, delegate(Exception e)
{
if (e is IOException)
{
FleckLog.Debug("Failed to send. Disconnecting.", e);
}
else
{
FleckLog.Info("Failed to send. Disconnecting.", e);
}
CloseSocket();
});
}
private void CloseSocket()
{
OnClose();
_closed = true;
Socket.Close();
Socket.Dispose();
}
}
public class WebSocketConnectionInfo : IWebSocketConnectionInfo
{
private const string CookiePattern = "((;\\s)*(?<cookie_name>[^=]+)=(?<cookie_value>[^\\;]+))+";
private static readonly Regex CookieRegex = new Regex("((;\\s)*(?<cookie_name>[^=]+)=(?<cookie_value>[^\\;]+))+");
public string SubProtocol { get; private set; }
public string Origin { get; private set; }
public string Host { get; private set; }
public string Path { get; private set; }
public string ClientIpAddress { get; set; }
public int ClientPort { get; set; }
public Guid Id { get; set; }
public IDictionary<string, string> Cookies { get; private set; }
public static WebSocketConnectionInfo Create(WebSocketHttpRequest request, string clientIp, int clientPort)
{
WebSocketConnectionInfo webSocketConnectionInfo = new WebSocketConnectionInfo
{
Origin = (request["Origin"] ?? request["Sec-WebSocket-Origin"]),
Host = request["Host"],
SubProtocol = request["Sec-WebSocket-Protocol"],
Path = request.Path,
ClientIpAddress = clientIp,
ClientPort = clientPort
};
string text = request["Cookie"];
if (text != null)
{
Match match = CookieRegex.Match(text);
CaptureCollection captures = match.Groups["cookie_name"].Captures;
CaptureCollection captures2 = match.Groups["cookie_value"].Captures;
for (int i = 0; i < captures.Count; i++)
{
string key = captures[i].ToString();
string value = captures2[i].ToString();
webSocketConnectionInfo.Cookies[key] = value;
}
}
return webSocketConnectionInfo;
}
private WebSocketConnectionInfo()
{
Cookies = new Dictionary<string, string>();
Id = Guid.NewGuid();
}
}
public class WebSocketException : Exception
{
public ushort StatusCode { get; private set; }
public WebSocketException(ushort statusCode)
{
StatusCode = statusCode;
}
public WebSocketException(ushort statusCode, string message)
: base(message)
{
StatusCode = statusCode;
}
public WebSocketException(ushort statusCode, string message, Exception innerException)
: base(message, innerException)
{
StatusCode = statusCode;
}
}
public class WebSocketHttpRequest
{
private readonly IDictionary<string, string> _headers = new Dictionary<string, string>();
public string Method { get; set; }
public string Path { get; set; }
public string Body { get; set; }
public string Scheme { get; set; }
public byte[] Bytes { get; set; }
public string this[string name]
{
get
{
if (!_headers.TryGetValue(name, out var value))
{
return null;
}
return value;
}
}
public IDictionary<string, string> Headers => _headers;
}
public class WebSocketServer : IWebSocketServer, IDisposable
{
private readonly string _scheme;
private Action<IWebSocketConnection> _config;
public ISocket ListenerSocket { get; set; }
public string Location { get; private set; }
public int Port { get; private set; }
public X509Certificate2 Certificate { get; set; }
public bool IsSecure
{
get
{
if (_scheme == "wss")
{
return Certificate != null;
}
return false;
}
}
public WebSocketServer(string location)
: this(8181, location)
{
}
public WebSocketServer(int port, string location)
{
Uri uri = new Uri(location);
Port = ((uri.Port > 0) ? uri.Port : port);
Location = location;
_scheme = uri.Scheme;
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
ListenerSocket = new SocketWrapper(socket);
}
public void Dispose()
{
ListenerSocket.Dispose();
}
public void Start(Action<IWebSocketConnection> config)
{
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, Port);
ListenerSocket.Bind(ipLocal);
ListenerSocket.Listen(100);
FleckLog.Info("Server started at " + Location);
if (_scheme == "wss" && Certificate == null)
{
FleckLog.Error("Scheme cannot be 'wss' without a Certificate");
return;
}
ListenForClients();
_config = config;
}
private void ListenForClients()
{
ListenerSocket.Accept(OnClientConnect, delegate(Exception e)
{
FleckLog.Error("Listener socket is closed", e);
});
}
private void OnClientConnect(ISocket clientSocket)
{
FleckLog.Debug($"Client connected from {clientSocket.RemoteIpAddress}:{clientSocket.RemotePort.ToString(CultureInfo.InvariantCulture)}");
ListenForClients();
WebSocketConnection connection = null;
connection = new WebSocketConnection(clientSocket, _config, (byte[] bytes) => RequestParser.Parse(bytes, _scheme), (WebSocketHttpRequest r) => HandlerFactory.BuildHandler(r, delegate(string s)
{
connection.OnMessage(s);
}, connection.Close, delegate(byte[] b)
{
connection.OnBinary(b);
}));
if (IsSecure)
{
FleckLog.Debug("Authenticating Secure Connection");
clientSocket.Authenticate(Certificate, connection.StartReceiving, delegate(Exception e)
{
FleckLog.Warn("Failed to Authenticate", e);
});
}
else
{
connection.StartReceiving();
}
}
}
public static class WebSocketStatusCodes
{
public const ushort NormalClosure = 1000;
public const ushort GoingAway = 1001;
public const ushort ProtocolError = 1002;
public const ushort UnsupportedDataType = 1003;
public const ushort NoStatusReceived = 1005;
public const ushort AbnormalClosure = 1006;
public const ushort InvalidFramePayloadData = 1007;
public const ushort PolicyViolation = 1008;
public const ushort MessageTooBig = 1009;
public const ushort MandatoryExt = 1010;
public const ushort InternalServerError = 1011;
public const ushort TlsHandshake = 1015;
public const ushort ApplicationError = 3000;
public static ushort[] ValidCloseCodes = new ushort[9] { 1000, 1001, 1002, 1003, 1007, 1008, 1009, 1010, 1011 };
public static bool Contains(ushort code)
{
for (int i = 0; i < ValidCloseCodes.Length; i++)
{
if (ValidCloseCodes[i] == code)
{
return true;
}
}
return false;
}
}
}
namespace Fleck2.Interfaces
{
public interface ICancellationToken
{
void ThrowIfCancellationRequested();
}
public interface IHandler
{
byte[] CreateHandshake();
void Receive(IEnumerable<byte> data);
byte[] FrameText(string text);
byte[] FrameBinary(byte[] bytes);
byte[] FrameClose(int code);
}
public interface ISocket
{
bool Connected { get; }
string RemoteIpAddress { get; }
int RemotePort { get; }
Stream Stream { get; }
bool NoDelay { get; set; }
void Accept(Fleck2Extensions.Action<ISocket> callback, Fleck2Extensions.Action<Exception> error);
void Send(byte[] buffer, Fleck2Extensions.Action callback, Fleck2Extensions.Action<Exception> error);
void Receive(byte[] buffer, Fleck2Extensions.Action<int> callback, Fleck2Extensions.Action<Exception> error, int offset = 0);
void Authenticate(X509Certificate2 certificate, Fleck2Extensions.Action callback, Fleck2Extensions.Action<Exception> error);
void Dispose();
void Close();
void Bind(EndPoint ipLocal);
void Listen(int backlog);
}
public interface IWebSocketConnection
{
Fleck2Extensions.Action OnOpen { get; set; }
Fleck2Extensions.Action OnClose { get; set; }
Action<string> OnMessage { get; set; }
Action<byte[]> OnBinary { get; set; }
Action<Exception> OnError { get; set; }
IWebSocketConnectionInfo ConnectionInfo { get; }
void Send(string message);
void Send(byte[] message);
void Close();
}
public interface IWebSocketConnectionInfo
{
string SubProtocol { get; }
string Origin { get; }
string Host { get; }
string Path { get; }
string ClientIpAddress { get; }
int ClientPort { get; }
IDictionary<string, string> Cookies { get; }
Guid Id { get; }
}
public interface IWebSocketServer : IDisposable
{
void Start(Action<IWebSocketConnection> config);
}
}
namespace Fleck2.Handlers
{
public class ComposableHandler : IHandler
{
public Fleck2Extensions.Func<byte[]> Handshake = () => new byte[0];
public Fleck2Extensions.Func<string, byte[]> TextFrame = (string x) => new byte[0];
public Fleck2Extensions.Func<byte[], byte[]> BinaryFrame = (byte[] x) => new byte[0];
public Action<List<byte>> ReceiveData = delegate
{
};
public Fleck2Extensions.Func<int, byte[]> CloseFrame = (int i) => new byte[0];
private readonly List<byte> _data = new List<byte>();
public byte[] CreateHandshake()
{
return Handshake();
}
public void Receive(IEnumerable<byte> data)
{
_data.AddRange(data);
ReceiveData(_data);
}
public byte[] FrameText(string text)
{
return TextFrame(text);
}
public byte[] FrameBinary(byte[] bytes)
{
return BinaryFrame(bytes);
}
public byte[] FrameClose(int code)
{
return CloseFrame(code);
}
}
public static class Draft76Handler
{
private const byte End = byte.MaxValue;
private const byte Start = 0;
private const int MaxSize = 5242880;
public static IHandler Create(WebSocketHttpRequest request, Action<string> onMessage)
{
return new ComposableHandler
{
TextFrame = FrameText,
Handshake = () => Handshake(request),
ReceiveData = delegate(List<byte> data)
{
ReceiveData(onMessage, data);
}
};
}
public static void ReceiveData(Action<string> onMessage, List<byte> data)
{
while (data.Count > 0)
{
if (data[0] != 0)
{
throw new WebSocketException(1007);
}
int num = data.IndexOf(byte.MaxValue);
if (num < 0)
{
break;
}
if (num > 5242880)
{
throw new WebSocketException(1009);
}
byte[] bytes = data.Skip(1).Take(num - 1).ToArray();
data.RemoveRange(0, num + 1);
string obj = Encoding.UTF8.GetString(bytes);
onMessage(obj);
}
}
public static byte[] FrameText(string data)
{
byte[] bytes = Encoding.UTF8.GetBytes(data);
byte[] array = new byte[bytes.Length + 2];
array[0] = 0;
array[^1] = byte.MaxValue;
Array.Copy(bytes, 0, array, 1, bytes.Length);
return array;
}
public static byte[] Handshake(WebSocketHttpRequest request)
{
FleckLog.Debug("Building Draft76 Response");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
stringBuilder.Append("Upgrade: WebSocket\r\n");
stringBuilder.Append("Connection: Upgrade\r\n");
stringBuilder.AppendFormat("Sec-WebSocket-Origin: {0}\r\n", request["Origin"]);
stringBuilder.AppendFormat("Sec-WebSocket-Location: {0}://{1}{2}\r\n", request.Scheme, request["Host"], request.Path);
if (request.Headers.ContainsKey("Sec-WebSocket-Protocol"))
{
stringBuilder.AppendFormat("Sec-WebSocket-Protocol: {0}\r\n", request["Sec-WebSocket-Protocol"]);
}
stringBuilder.Append("\r\n");
string key = request["Sec-WebSocket-Key1"];
string key2 = request["Sec-WebSocket-Key2"];
ArraySegment<byte> challenge = new ArraySegment<byte>(request.Bytes, request.Bytes.Length - 8, 8);
byte[] array = CalculateAnswerBytes(key, key2, challenge);
byte[] array2 = Encoding.ASCII.GetBytes(stringBuilder.ToString());
int num = array2.Length;
Array.Resize(ref array2, num + array.Length);
Array.Copy(array, 0, array2, num, array.Length);
return array2;
}
public static byte[] CalculateAnswerBytes(string key1, string key2, ArraySegment<byte> challenge)
{
byte[] sourceArray = ParseKey(key1);
byte[] sourceArray2 = ParseKey(key2);
byte[] array = new byte[16];
Array.Copy(sourceArray, 0, array, 0, 4);
Array.Copy(sourceArray2, 0, array, 4, 4);
Array.Copy(challenge.Array, challenge.Offset, array, 8, 8);
return MD5.Create().ComputeHash(array);
}
private static byte[] ParseKey(string key)
{
int num = 0;
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < key.Length; i++)
{
if (char.IsWhiteSpace(key[i]))
{
num++;
}
if (char.IsDigit(key[i]))
{
stringBuilder.Append(key[i]);
}
}
byte[] bytes = BitConverter.GetBytes((int)(long.Parse(stringBuilder.ToString()) / num));
if (BitConverter.IsLittleEndian)
{
Array.Reverse((Array)bytes);
}
return bytes;
}
}
public static class Hybi13Handler
{
private const string WebSocketResponseGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
public static IHandler Create(WebSocketHttpRequest request, Action<string> onMessage, Fleck2Extensions.Action onClose, Action<byte[]> onBinary)
{
ReadState readState = new ReadState();
return new ComposableHandler
{
Handshake = () => BuildHandshake(request),
TextFrame = (string data) => FrameData(Encoding.UTF8.GetBytes(data), FrameType.Text),
BinaryFrame = (byte[] data) => FrameData(data, FrameType.Binary),
CloseFrame = (int i) => FrameData(i.ToBigEndianBytes<ushort>(), FrameType.Close),
ReceiveData = delegate(List<byte> bytes)
{
ReceiveData(bytes, readState, delegate(FrameType op, byte[] data)
{
ProcessFrame(op, data, onMessage, onClose, onBinary);
});
}
};
}
public static byte[] FrameData(byte[] payload, FrameType frameType)
{
MemoryStream memoryStream = new MemoryStream();
byte value = (byte)(frameType + 128);
memoryStream.WriteByte(value);
if (payload.Length > 65535)
{
memoryStream.WriteByte(127);
byte[] array = payload.Length.ToBigEndianBytes<ushort>();
memoryStream.Write(array, 0, array.Length);
}
else if (payload.Length > 125)
{
memoryStream.WriteByte(126);
byte[] array2 = payload.Length.ToBigEndianBytes<ushort>();
memoryStream.Write(array2, 0, array2.Length);
}
else
{
memoryStream.WriteByte((byte)payload.Length);
}
memoryStream.Write(payload, 0, payload.Length);
return memoryStream.ToArray();
}
public static void ReceiveData(List<byte> data, ReadState readState, Fleck2Extensions.Action<FrameType, byte[]> processFrame)
{
while (data.Count >= 2)
{
bool flag = (data[0] & 0x80) != 0;
int num = data[0] & 0x70;
FrameType frameType = (FrameType)(data[0] & 0xF);
bool num2 = (data[1] & 0x80) != 0;
int num3 = data[1] & 0x7F;
if (!num2 || !Enum.IsDefined(typeof(FrameType), frameType) || num != 0 || (frameType == FrameType.Continuation && !readState.FrameType.HasValue))
{
throw new WebSocketException(1002);
}
int num4 = 2;
int num5;
switch (num3)
{
case 127:
if (data.Count < num4 + 8)
{
return;
}
num5 = data.Skip(num4).Take(8).ToArray()
.ToLittleEndianInt();
num4 += 8;
break;
case 126:
if (data.Count < num4 + 2)
{
return;
}
num5 = data.Skip(num4).Take(2).ToArray()
.ToLittleEndianInt();
num4 += 2;
break;
default:
num5 = num3;
break;
}
if (data.Count < num4 + 4)
{
break;
}
List<byte> maskBytes = data.Skip(num4).Take(4).ToList();
num4 += 4;
if (data.Count < num4 + num5)
{
break;
}
int i = 0;
IEnumerable<byte> collection = from value in data.Skip(num4).Take(num5)
select (byte)(value ^ maskBytes[i++ % 4]);
readState.Data.AddRange(collection);
data.RemoveRange(0, num4 + num5);
if (frameType != FrameType.Continuation)
{
readState.FrameType = frameType;
}
if (flag && readState.FrameType.HasValue)
{
byte[] u = readState.Data.ToArray();
FrameType? frameType2 = readState.FrameType;
readState.Clear();
processFrame(frameType2.Value, u);
}
}
}
public static void ProcessFrame(FrameType frameType, byte[] data, Action<string> onMessage, Fleck2Extensions.Action onClose, Action<byte[]> onBinary)
{
switch (frameType)
{
case FrameType.Close:
if (data.Length == 1 || data.Length > 125)
{
throw new WebSocketException(1002);
}
if (data.Length >= 2)
{
ushort num = (ushort)data.Take(2).ToArray().ToLittleEndianInt();
if (!WebSocketStatusCodes.Contains(num) && (num < 3000 || num > 4999))
{
throw new WebSocketException(1002);
}
}
if (data.Length > 2)
{
ReadUtf8PayloadData(data.Skip(2));
}
onClose();
break;
case FrameType.Binary:
onBinary(data);
break;
case FrameType.Text:
onMessage(ReadUtf8PayloadData(data));
break;
default:
FleckLog.Debug("Received unhandled " + frameType);
break;
}
}
public static byte[] BuildHandshake(WebSocketHttpRequest request)
{
FleckLog.Debug("Building Hybi-14 Response");
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("HTTP/1.1 101 Switching Protocols\r\n");
stringBuilder.Append("Upgrade: websocket\r\n");
stringBuilder.Append("Connection: Upgrade\r\n");
string arg = CreateResponseKey(request["Sec-WebSocket-Key"]);
stringBuilder.AppendFormat("Sec-WebSocket-Accept: {0}\r\n", arg);
stringBuilder.Append("\r\n");
return Encoding.ASCII.GetBytes(stringBuilder.ToString());
}
public static string CreateResponseKey(string requestKey)
{
string s = requestKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
return Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(s)));
}
private static string ReadUtf8PayloadData(byte[] bytes)
{
UTF8Encoding uTF8Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
try
{
return uTF8Encoding.GetString(bytes);
}
catch (ArgumentException)
{
throw new WebSocketException(1007);
}
}
}
}
namespace H3Status
{
internal static class Config
{
public static ConfigEntry<bool> ServerEnabled;
public static ConfigEntry<int> ServerPort;
public static ConfigEntry<bool> LogScoreEvents;
public static ConfigEntry<bool> SceneEvent;
public static ConfigEntry<bool> AmmoEvent;
public static ConfigEntry<bool> HealthEvent;
public static ConfigEntry<bool> BuffEvent;
public static ConfigEntry<bool> TNHLevelEvent;
public static ConfigEntry<bool> TNHPhaseEvent;
public static ConfigEntry<bool> TNHHoldPhaseEvent;
public static ConfigEntry<bool> TNHScoreEvent;
public static ConfigEntry<bool> TNHEncryptionDestroyed;
public static ConfigEntry<bool> TNHTokenEvent;
private static ConfigFile _configFile;
private static ConfigEntry<T> Bind<T>(this ConfigFile config, string section, string key, T defaultValue, Action<T> callback)
{
ConfigEntry<T> entry = config.Bind<T>(section, key, defaultValue, (ConfigDescription)null);
entry.SettingChanged += delegate
{
callback(entry.Value);
};
return entry;
}
public static void Init(ConfigFile config)
{
_configFile = config;
string text = "1. General";
string text2 = "2. Event Types";
ServerEnabled = config.Bind(text, "Server Enabled", defaultValue: true, OnServerEnabledChanged);
ServerPort = config.Bind(text, "Server Port", 9504, OnServerPortChanged);
LogScoreEvents = config.Bind<bool>(text, "Log Score Events", false, (ConfigDescription)null);
SceneEvent = config.Bind<bool>(text2, "Scene Changed", true, (ConfigDescription)null);
AmmoEvent = config.Bind<bool>(text2, "Score Changed", true, (ConfigDescription)null);
HealthEvent = config.Bind<bool>(text2, "Health Changed", true, (ConfigDescription)null);
BuffEvent = config.Bind<bool>(text2, "Powerup Activated", true, (ConfigDescription)null);
TNHLevelEvent = config.Bind<bool>(text2, "T&H Level Started", true, (ConfigDescription)null);
TNHPhaseEvent = config.Bind<bool>(text2, "T&H Phase Changed", true, (ConfigDescription)null);
TNHHoldPhaseEvent = config.Bind<bool>(text2, "T&H Hold Phase Changed", true, (ConfigDescription)null);
TNHScoreEvent = config.Bind<bool>(text2, "T&H Score Changed", true, (ConfigDescription)null);
TNHEncryptionDestroyed = config.Bind<bool>(text2, "T&H Encryption Destroyed", true, (ConfigDescription)null);
TNHTokenEvent = config.Bind<bool>(text2, "T&H Tokens Changed", true, (ConfigDescription)null);
}
private static void OnServerEnabledChanged(bool enabled)
{
if (enabled)
{
Plugin.Start();
}
else
{
Plugin.Stop();
}
}
private static void OnServerPortChanged(int port)
{
Server.Stop();
Server.Start(port);
}
}
[BepInProcess("h3vr.exe")]
[BepInPlugin("xyz.bacur.plugins.h3status", "H3Status", "0.5.1")]
public class Plugin : BaseUnityPlugin
{
public const string Guid = "xyz.bacur.plugins.h3status";
public const string Name = "H3Status";
public const string Version = "0.5.1";
internal static ManualLogSource Logger;
internal static Harmony Patcher;
protected void Awake()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected O, but got Unknown
Logger = ((BaseUnityPlugin)this).Logger;
Patcher = new Harmony("xyz.bacur.plugins.h3status");
Config.Init(((BaseUnityPlugin)this).Config);
if (!Config.ServerEnabled.Value)
{
Logger.LogWarning((object)"Server disabled in config");
}
else
{
Start();
}
}
protected void OnDestroy()
{
Stop();
}
internal static void Start()
{
Server.Start(Config.ServerPort.Value);
Harmony patcher = Patcher;
if (patcher != null)
{
patcher.PatchAll(typeof(SceneHandler));
}
Harmony patcher2 = Patcher;
if (patcher2 != null)
{
patcher2.PatchAll(typeof(TNHScoreHandler));
}
Harmony patcher3 = Patcher;
if (patcher3 != null)
{
patcher3.PatchAll(typeof(TNHPhaseHandler));
}
Harmony patcher4 = Patcher;
if (patcher4 != null)
{
patcher4.PatchAll(typeof(PlayerHealthHandler));
}
Harmony patcher5 = Patcher;
if (patcher5 != null)
{
patcher5.PatchAll(typeof(WeaponAmmoHandler));
}
}
internal static void Stop()
{
Server.Stop();
Harmony patcher = Patcher;
if (patcher != null)
{
patcher.UnpatchSelf();
}
}
}
internal static class Server
{
private static WebSocketServer _server;
private static readonly List<IWebSocketConnection> _instances = new List<IWebSocketConnection>();
private static readonly JsonSerializerSettings _jsonSettings = new JsonSerializerSettings
{
ContractResolver = (IContractResolver)new CamelCasePropertyNamesContractResolver(),
Converters = new List<JsonConverter>(1) { (JsonConverter)new StringEnumConverter(false) }
};
public static void Start(int port)
{
if (_server != null)
{
return;
}
FleckLog.Level = LogLevel.Warn;
_server = new WebSocketServer($"ws://0.0.0.0:{port}");
_server.Start(delegate(IWebSocketConnection instance)
{
instance.OnOpen = delegate
{
_instances.Add(instance);
instance.Send(JsonConvert.SerializeObject((object)new Event
{
Type = EventType.Hello,
Status = VersionHandler.GetVersionInfo()
}, _jsonSettings));
};
instance.OnClose = delegate
{
_instances.Remove(instance);
};
});
Plugin.Logger.LogInfo((object)$"Server started on port {port}");
}
public static void Stop()
{
if (_server == null)
{
return;
}
Plugin.Logger.LogInfo((object)"Server shutting down");
foreach (IWebSocketConnection instance in _instances)
{
instance.Close();
}
_server.Dispose();
_server = null;
}
public static void SendMessage(Event evt)
{
string message = JsonConvert.SerializeObject((object)evt, _jsonSettings);
foreach (IWebSocketConnection instance in _instances)
{
instance.Send(message);
}
}
}
}
namespace H3Status.Utils
{
internal static class AmmoReader
{
public static void GetAmmo(string path)
{
//IL_0077: 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_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogInfo((object)"WRITING FILE");
StreamWriter streamWriter = new StreamWriter(path, append: false);
try
{
ManagerSingleton<AM>.Instance.GenerateFireArmRoundDictionaries();
}
catch
{
Plugin.Logger.LogInfo((object)"TypeDict already generated");
}
foreach (KeyValuePair<FireArmRoundType, Dictionary<FireArmRoundClass, DisplayDataClass>> item in ManagerSingleton<AM>.Instance.TypeDic)
{
foreach (KeyValuePair<FireArmRoundClass, DisplayDataClass> item2 in item.Value)
{
string text = ((object)item.Key/*cast due to .constrained prefix*/).ToString() + "," + ((object)item2.Key/*cast due to .constrained prefix*/).ToString() + "," + ((Object)item2.Value.Mesh).name;
Plugin.Logger.LogInfo((object)text);
streamWriter.WriteLine(text);
}
}
streamWriter.Flush();
streamWriter.Close();
Plugin.Logger.LogInfo((object)"DONE");
}
public unsafe static void GetShells(string path)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
Plugin.Logger.LogInfo((object)"WRITING FILE");
StreamWriter streamWriter = new StreamWriter(path, append: false);
foreach (FireArmRoundType type in ManagerSingleton<AM>.Instance.TypeList)
{
FVRFireArmRound component = ((AnvilAsset)AM.GetRoundSelfPrefab(type, AM.GetDefaultRoundClass(type))).GetGameObject().GetComponent<FVRFireArmRound>();
if ((Object)(object)component != (Object)null)
{
component.Fire();
if ((Object)(object)component != (Object)null && (Object)(object)component.FiredRenderer != (Object)null)
{
string text = ((object)(*(FireArmRoundType*)(&type))/*cast due to .constrained prefix*/).ToString() + "," + ((Object)((Component)component.FiredRenderer).gameObject.GetComponent<MeshFilter>().sharedMesh).name;
Plugin.Logger.LogInfo((object)text);
streamWriter.WriteLine(text);
}
}
}
streamWriter.Flush();
streamWriter.Close();
Plugin.Logger.LogInfo((object)"DONE");
}
}
internal static class WeaponReader
{
public static void GetWeapons(string path, ItemSpawnerV2 spawner)
{
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0200: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_024f: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_027b: Unknown result type (might be due to invalid IL or missing references)
//IL_0280: Unknown result type (might be due to invalid IL or missing references)
//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0304: Unknown result type (might be due to invalid IL or missing references)
//IL_032b: Unknown result type (might be due to invalid IL or missing references)
//IL_0330: Unknown result type (might be due to invalid IL or missing references)
List<FVRObject> list = ManagerSingleton<IM>.Instance.odicTagCategory[(ObjectCategory)1];
int count = list.Count;
for (int i = 0; i < list.Count; i++)
{
bool flag = false;
FVRObject val = list[i];
if (val.OSple && val.SpawnedFromId != null && !(val.SpawnedFromId == string.Empty) && IM.HasSpawnedID(val.SpawnedFromId) && IM.GetSpawnerID(val.SpawnedFromId).IsDisplayedInMainEntry)
{
flag = true;
}
if (!flag)
{
list.RemoveAt(i--);
}
}
Plugin.Logger.LogInfo((object)$"Found {list.Count} guns ({count - list.Count} excluded)");
Plugin.Logger.LogInfo((object)"WRITING FILES");
List<string> list2 = new List<string> { "Cube", "Sphere", "Capsule", "Quad" };
foreach (FVRObject item in list)
{
string itemID = IM.GetSpawnerID(item.SpawnedFromId).ItemID;
Plugin.Logger.LogInfo((object)itemID);
GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)item).GetGameObject(), Vector3.zero, Quaternion.identity);
val2.SetActive(false);
StreamWriter streamWriter = new StreamWriter(path + "/" + itemID + ".csv", append: false);
MeshFilter[] componentsInChildren = val2.GetComponentsInChildren<MeshFilter>(false);
foreach (MeshFilter val3 in componentsInChildren)
{
if ((Object)(object)val3.sharedMesh != (Object)null)
{
string name = ((Object)val3.sharedMesh).name;
if (!list2.Contains(name))
{
string value = ((Object)val3.sharedMesh).name + "," + ((Component)val3).transform.position.x.ToString("F6") + "," + ((Component)val3).transform.position.y.ToString("F6") + "," + ((Component)val3).transform.position.z.ToString("F6") + "," + ((Component)val3).transform.rotation.x.ToString("F6") + "," + ((Component)val3).transform.rotation.y.ToString("F6") + "," + ((Component)val3).transform.rotation.z.ToString("F6") + "," + ((Component)val3).transform.localScale.x.ToString("F6") + "," + ((Component)val3).transform.localScale.y.ToString("F6") + "," + ((Component)val3).transform.localScale.z.ToString("F6");
streamWriter.WriteLine(value);
}
}
}
Object.Destroy((Object)(object)val2);
streamWriter.Flush();
streamWriter.Close();
}
Plugin.Logger.LogInfo((object)"DONE");
}
}
}
namespace H3Status.Patches
{
internal static class VersionHandler
{
private static VersionStatus versionStatus;
public static VersionStatus GetVersionInfo()
{
versionStatus.Version = "0.5.1";
versionStatus.GameVersion = $"{GM.Version_UpdateNumber}.{GM.Version_AlphaNumber}.{GM.Version_PatchNumber}";
return versionStatus;
}
}
[HarmonyPatch]
internal static class SceneHandler
{
public static string activeScene = string.Empty;
private static SceneStatus sceneStatus = default(SceneStatus);
[HarmonyPostfix]
[HarmonyPatch(typeof(SteamVR_LoadLevel), "Begin")]
private static void SceneEvent(string levelName)
{
if (Config.SceneEvent.Value)
{
activeScene = levelName;
sceneStatus = new SceneStatus
{
Name = levelName
};
Server.SendMessage(new Event
{
Type = EventType.SceneEvent,
Status = sceneStatus
});
}
}
}
[HarmonyPatch]
internal static class TNHPhaseHandler
{
private static readonly string[] holdNamesInstitution = new string[20]
{
"HUB", "LIBRARY", "GARDEN", "ATRIUM", "LOBBY", "HEDRONS", "TURBINE", "HYDRO", "SPILLWAY", "RODS",
"STORAGE", "APRROACH", "CROSSOVER", "PIPEWORKS", "VOID", "CONCOURSE", "BUNKER", "INCLINATOR", "ABYSS", "SUBSTATION"
};
private static readonly string[] supplyNamesInstitution = new string[16]
{
"ARRAY", "STUDIO", "SUITE", "LOFT", "PENTHOUSE", "GREENWALL", "FENESTRA", "JUDGEMENT", "PRESIDIO", "DISSONANCE",
"CLERESTORY", "HELIX", "FACILITY", "STACKS", "ALTAR", "PUMP"
};
private static bool isInitialized = false;
private static TNHLevelStatus levelStatus = default(TNHLevelStatus);
private static TNHPhaseStatus phaseStatus = default(TNHPhaseStatus);
private static TNHHoldPhaseStatus holdPhaseStatus = default(TNHHoldPhaseStatus);
[HarmonyPrefix]
[HarmonyPatch(typeof(TNH_Manager), "DelayedInit")]
private static void TNHLevelEventPre(TNH_Manager __instance)
{
isInitialized = __instance.m_hasInit;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_Manager), "DelayedInit")]
private static void TNHLevelEventPost(TNH_Manager __instance)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
if (Config.TNHLevelEvent.Value && !isInitialized && __instance.m_hasInit)
{
levelStatus = new TNHLevelStatus
{
Seed = __instance.HoldSequenceSeed,
EquipmentSeed = __instance.equipmentSeed,
LevelName = __instance.LevelName,
CharacterName = __instance.C.DisplayName,
ScoreMultiplier = TNHScoreHandler.GetMultiplier(),
AiDifficulty = __instance.AI_Difficulty,
RadarMode = __instance.RadarMode,
TargetMode = __instance.TargetMode,
HealthMode = __instance.HealthMode,
EquipmentMode = __instance.EquipmentMode
};
Server.SendMessage(new Event
{
Type = EventType.TNHLevelEvent,
Status = levelStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_Manager), "SetPhase")]
private static void TNHPhaseEvent(TNH_Phase p, TNH_Manager __instance)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
if (!Config.TNHPhaseEvent.Value)
{
return;
}
phaseStatus = new TNHPhaseStatus
{
Phase = p,
Level = __instance.m_level,
Count = __instance.m_maxLevels,
Seed = __instance.m_holdSequenceSeed,
Hold = __instance.m_curHoldIndex,
Supply = new List<int>(),
HoldName = null,
SupplyNames = null
};
foreach (int activeSupplyPointIndicy in __instance.m_activeSupplyPointIndicies)
{
phaseStatus.Supply.Add(activeSupplyPointIndicy);
}
if (SceneHandler.activeScene == "Institution")
{
phaseStatus.HoldName = holdNamesInstitution[__instance.m_curHoldIndex];
phaseStatus.SupplyNames = new List<string>();
foreach (int activeSupplyPointIndicy2 in __instance.m_activeSupplyPointIndicies)
{
phaseStatus.SupplyNames.Add(supplyNamesInstitution[activeSupplyPointIndicy2]);
}
}
Server.SendMessage(new Event
{
Type = EventType.TNHPhaseEvent,
Status = phaseStatus
});
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_HoldPoint), "BeginAnalyzing")]
[HarmonyPatch(typeof(TNH_HoldPoint), "IdentifyEncryption")]
[HarmonyPatch(typeof(TNH_HoldPoint), "CompletePhase")]
private static void TNHHoldPhaseEvent(TNH_HoldPoint __instance)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (Config.TNHHoldPhaseEvent.Value)
{
holdPhaseStatus = new TNHHoldPhaseStatus
{
Phase = __instance.m_state,
Level = __instance.m_phaseIndex,
Count = __instance.H.Phases.Count,
EncryptionType = __instance.m_curPhase.Encryption,
EncryptionCount = __instance.m_numTargsToSpawn,
EncryptionTime = 120f
};
Server.SendMessage(new Event
{
Type = EventType.TNHHoldPhaseEvent,
Status = holdPhaseStatus
});
}
}
}
[HarmonyPatch]
internal static class TNHScoreHandler
{
private static TNHScoreStatus scoreStatus = default(TNHScoreStatus);
private static TNHTokenStatus tokenStatus = default(TNHTokenStatus);
private static readonly int[] eventMultiplier = new int[15]
{
12000, 12, 1, 12, 300, 100, 100, 100, 100, 1,
250, 12, 1, 1, 250
};
private static readonly bool[] eventIsCounted = new bool[15]
{
true, true, false, true, true, true, true, false, false, false,
false, true, false, false, false
};
private static int GetEventScore(ScoringEvent ev, int num)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
return num * eventMultiplier[ev];
}
private static int GetTotalScore()
{
int num = 0;
int multiplier = GetMultiplier();
for (int i = 0; i <= 14; i++)
{
if (eventIsCounted[i])
{
num += GetEventScore((ScoringEvent)i, GM.TNH_Manager.Nums[i]);
}
}
return num * multiplier;
}
internal static int GetMultiplier()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Invalid comparison between Unknown and I4
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Invalid comparison between Unknown and I4
int num = 1;
if ((int)GM.TNHOptions.TargetModeSetting == 0)
{
num += 3;
}
else if ((int)GM.TNHOptions.TargetModeSetting == 1)
{
num += 2;
}
if ((int)GM.TNHOptions.AIDifficultyModifier == 0)
{
num += 3;
}
if ((int)GM.TNHOptions.RadarModeModifier == 0)
{
num += 2;
}
else if ((int)GM.TNHOptions.RadarModeModifier != 1)
{
num += 3;
}
return num;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_Manager), "IncrementScoringStat")]
private static void TNHScoreEvent(ScoringEvent ev, int num, TNH_Manager __instance)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
if (eventIsCounted[ev])
{
if (Config.LogScoreEvents.Value)
{
Plugin.Logger.LogMessage((object)$"{ev}: {GetEventScore(ev, num) * GetMultiplier()} ({GetEventScore(ev, num)}x{GetMultiplier()})");
}
if (Config.TNHScoreEvent.Value)
{
scoreStatus = new TNHScoreStatus
{
Type = ev,
Value = GetEventScore(ev, num),
Mult = GetMultiplier(),
Score = GetTotalScore()
};
Server.SendMessage(new Event
{
Type = EventType.TNHScoreEvent,
Status = scoreStatus
});
}
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_HoldPoint), "TargetDestroyed")]
private static void TNHEncryptionDestroyed()
{
if (Config.TNHEncryptionDestroyed.Value)
{
Server.SendMessage(new Event
{
Type = EventType.TNHEncryptionDestroyed
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_Manager), "AddTokens")]
private static void TNHTokenEventAdd(int i, TNH_Manager __instance)
{
if (Config.TNHTokenEvent.Value)
{
tokenStatus = new TNHTokenStatus
{
Change = i,
Tokens = __instance.m_numTokens
};
Server.SendMessage(new Event
{
Type = EventType.TNHTokenEvent,
Status = tokenStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(TNH_Manager), "SubtractTokens")]
private static void TNHTokenEventSubtract(int i, TNH_Manager __instance)
{
if (Config.TNHTokenEvent.Value)
{
tokenStatus = new TNHTokenStatus
{
Change = -i,
Tokens = __instance.m_numTokens
};
Server.SendMessage(new Event
{
Type = EventType.TNHTokenEvent,
Status = tokenStatus
});
}
}
}
[HarmonyPatch]
internal static class PlayerHealthHandler
{
private static HealthStatus healthStatus;
private static BuffStatus buffStatus;
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRPlayerBody), "RegisterPlayerHit")]
private static void HealthEventHit(float DamagePoints, bool FromSelf, int iff, FVRPlayerBody __instance)
{
if (Config.HealthEvent.Value)
{
healthStatus = new HealthStatus
{
Change = -(int)DamagePoints,
Health = (int)__instance.Health,
MaxHealth = (int)__instance.m_startingHealth
};
Server.SendMessage(new Event
{
Type = EventType.HealthEvent,
Status = healthStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRPlayerBody), "HarmPercent")]
private static void HealthEventHarm(float f, FVRPlayerBody __instance)
{
if (Config.HealthEvent.Value)
{
healthStatus = new HealthStatus
{
Change = -(int)(__instance.m_startingHealth * f),
Health = (int)__instance.Health,
MaxHealth = (int)__instance.m_startingHealth
};
Server.SendMessage(new Event
{
Type = EventType.HealthEvent,
Status = healthStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRPlayerBody), "Init")]
private static void HealthEventInit(FVRPlayerBody __instance)
{
if (Config.HealthEvent.Value)
{
healthStatus = new HealthStatus
{
Change = 0f,
Health = (int)__instance.Health,
MaxHealth = (int)__instance.m_startingHealth
};
Server.SendMessage(new Event
{
Type = EventType.HealthEvent,
Status = healthStatus
});
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(FVRPlayerBody), "SetHealthThreshold")]
private static void HealthEventUpdate(float h, FVRPlayerBody __instance)
{
if (Config.HealthEvent.Value)
{
healthStatus = new HealthStatus
{
Change = (int)(h - __instance.Health),
Health = (int)h,
MaxHealth = (int)h
};
Server.SendMessage(new Event
{
Type = EventType.HealthEvent,
Status = healthStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRPlayerBody), "HealPercent")]
private static void HealthEventHeal(float f, FVRPlayerBody __instance)
{
if (Config.HealthEvent.Value)
{
healthStatus = new HealthStatus
{
Change = (int)(__instance.m_startingHealth * f),
Health = (int)__instance.Health,
MaxHealth = (int)__instance.m_startingHealth
};
Server.SendMessage(new Event
{
Type = EventType.HealthEvent,
Status = healthStatus
});
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRPlayerBody), "ActivatePower")]
private static void BuffEvent(PowerupType type, PowerUpIntensity intensity, PowerUpDuration d, bool isPuke, bool isInverted, float DurationOverride = -1f)
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
if (Config.BuffEvent.Value)
{
float duration = 1f;
switch ((int)d)
{
case 0:
duration = 30f;
break;
case 1:
duration = 20f;
break;
case 2:
duration = 10f;
break;
case 3:
duration = 2f;
break;
case 4:
duration = 40f;
break;
}
if (DurationOverride > 0f)
{
duration = DurationOverride;
}
buffStatus = new BuffStatus
{
Type = type,
Duration = duration,
Inverted = isInverted
};
Server.SendMessage(new Event
{
Type = EventType.BuffEvent,
Status = buffStatus
});
}
}
}
[HarmonyPatch]
internal static class WeaponAmmoHandler
{
private static bool isUpdatePending;
private static AmmoStatus ammoStatus;
[HarmonyPrefix]
[HarmonyPatch(typeof(FVRFireArm), "FVRFixedUpdate")]
private static void HandlePendingEvent()
{
if (Config.AmmoEvent.Value && isUpdatePending)
{
isUpdatePending = false;
Server.SendMessage(new Event
{
Type = EventType.AmmoEvent,
Status = ammoStatus
});
}
}
private static void UpdateAmmoCount(FVRFireArm fireArm)
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: 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_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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)fireArm == (Object)null || (Object)(object)((FVRInteractiveObject)fireArm).m_hand == (Object)null)
{
return;
}
string weapon = string.Empty;
int hand = (((FVRInteractiveObject)fireArm).m_hand.IsThisTheRightHand ? 1 : 0);
FireArmRoundType roundType = fireArm.RoundType;
FireArmRoundClass roundClass = (FireArmRoundClass)0;
int num = 0;
int num2 = 0;
int num3 = 0;
try
{
roundClass = AM.GetDefaultRoundClass(fireArm.RoundType);
}
catch
{
}
if ((Object)(object)((FVRPhysicalObject)fireArm).ObjectWrapper != (Object)null)
{
weapon = ((!IM.HasSpawnedID(((FVRPhysicalObject)fireArm).ObjectWrapper.ItemID)) ? ((FVRPhysicalObject)fireArm).ObjectWrapper.DisplayName : IM.GetSpawnerID(((FVRPhysicalObject)fireArm).ObjectWrapper.ItemID).DisplayName);
}
if ((Object)(object)fireArm.Magazine != (Object)null)
{
num3 += fireArm.Magazine.m_capacity;
num += fireArm.Magazine.m_numRounds;
if (fireArm.Magazine.LoadedRounds != null)
{
for (int i = 0; i < fireArm.Magazine.LoadedRounds.Length; i++)
{
if (fireArm.Magazine.LoadedRounds[i] != null)
{
roundClass = fireArm.Magazine.LoadedRounds[i].LR_Class;
}
}
}
}
if ((Object)(object)fireArm.BeltDD != (Object)null)
{
num += fireArm.BeltDD.m_roundsOnBelt;
}
if (fireArm.FChambers != null)
{
num3 += fireArm.FChambers.Count;
foreach (FVRFireArmChamber fChamber in fireArm.FChambers)
{
if (!((Object)(object)fChamber.m_round == (Object)null))
{
if (fChamber.IsSpent)
{
num2++;
continue;
}
roundClass = fChamber.m_round.RoundClass;
num++;
}
}
}
ammoStatus = new AmmoStatus
{
Weapon = weapon,
Hand = hand,
RoundType = roundType,
RoundClass = roundClass,
Current = num,
Spent = num2,
Capacity = num3
};
isUpdatePending = true;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRFireArmMagazine), "AddRound", new Type[]
{
typeof(FireArmRoundClass),
typeof(bool),
typeof(bool)
})]
[HarmonyPatch(typeof(FVRFireArmMagazine), "AddRound", new Type[]
{
typeof(FVRFireArmRound),
typeof(bool),
typeof(bool),
typeof(bool)
})]
private static void AmmoEventMagazine(FVRFireArmMagazine __instance)
{
if (Config.AmmoEvent.Value)
{
UpdateAmmoCount(__instance.FireArm);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRFireArm), "LoadMag")]
[HarmonyPatch(typeof(FVRFireArm), "EjectMag")]
private static void AmmoEventFireArm(FVRFireArm __instance)
{
if (Config.AmmoEvent.Value)
{
UpdateAmmoCount(__instance);
}
}
[HarmonyPostfix]
[HarmonyPatch(typeof(FVRFireArmChamber), "UpdateProxyDisplay")]
private static void AmmoEventChamber(FVRFireArmChamber __instance)
{
if (!Config.AmmoEvent.Value)
{
return;
}
if ((Object)(object)__instance.Firearm != (Object)null)
{
UpdateAmmoCount(__instance.Firearm);
return;
}
Transform parent = ((Component)__instance).transform.parent;
FVRFireArm val = ((parent != null) ? ((Component)parent).gameObject.GetComponent<FVRFireArm>() : null);
if ((Object)(object)val != (Object)null)
{
UpdateAmmoCount(val);
}
}
}
}
namespace H3Status.Model
{
internal struct Event
{
public EventType Type { get; set; }
public object? Status { get; set; }
}
[JsonConverter(typeof(StringEnumConverter), new object[] { true })]
internal enum EventType
{
Hello,
SceneEvent,
AmmoEvent,
HealthEvent,
BuffEvent,
TNHLevelEvent,
TNHPhaseEvent,
TNHHoldPhaseEvent,
TNHScoreEvent,
TNHEncryptionDestroyed,
TNHTokenEvent
}
internal struct VersionStatus
{
public string Version { get; set; }
public string GameVersion { get; set; }
}
internal struct SceneStatus
{
public string Name { get; set; }
}
internal struct AmmoStatus
{
public string Weapon { get; set; }
public FireArmRoundType RoundType { get; set; }
public FireArmRoundClass RoundClass { get; set; }
public int Hand { get; set; }
public int Current { get; set; }
public int Spent { get; set; }
public int Capacity { get; set; }
}
internal struct HealthStatus
{
public float Change { get; set; }
public float Health { get; set; }
public float MaxHealth { get; set; }
}
internal struct BuffStatus
{
public PowerupType Type { get; set; }
public float Duration { get; set; }
public bool Inverted { get; set; }
}
internal struct TNHLevelStatus
{
public int Seed { get; set; }
public int EquipmentSeed { get; set; }
public string LevelName { get; set; }
public string CharacterName { get; set; }
public int ScoreMultiplier { get; set; }
public TNHModifier_AIDifficulty AiDifficulty { get; set; }
public TNHModifier_RadarMode RadarMode { get; set; }
public TNHSetting_TargetMode TargetMode { get; set; }
public TNHSetting_HealthMode HealthMode { get; set; }
public TNHSetting_EquipmentMode EquipmentMode { get; set; }
}
internal struct TNHPhaseStatus
{
public TNH_Phase Phase { get; set; }
public int Level { get; set; }
public int Count { get; set; }
public int Seed { get; set; }
public int Hold { get; set; }
public List<int> Supply { get; set; }
public string? HoldName { get; set; }
public List<string>? SupplyNames { get; set; }
}
internal struct TNHHoldPhaseStatus
{
public HoldState Phase { get; set; }
public int Level { get; set; }
public int Count { get; set; }
public TNH_EncryptionType EncryptionType { get; set; }
public int EncryptionCount { get; set; }
public float EncryptionTime { get; set; }
}
internal struct TNHScoreStatus
{
public ScoringEvent Type { get; set; }
public int Value { get; set; }
public int Mult { get; set; }
public int Score { get; set; }
}
internal struct TNHTokenStatus
{
public int Change { get; set; }
public int Tokens { get; set; }
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public class ExtensionAttribute : Attribute
{
}
}