mirror of
https://github.com/NuclearPowered/Reactor.git
synced 2026-10-19 15:51:54 +00:00
1 parent
5cc08363c7
commit
b7971d36a8
66 files changed
+652
-618
No files matched your search
@@ -6,3 +6,4 @@ riderModule.iml
|
|||||||
.idea
|
.idea
|
||||||
/tools
|
/tools
|
||||||
.vscode
|
.vscode
|
||||||
|
*.DotSettings.user
|
||||||
@@ -6,7 +6,8 @@ using BenchmarkDotNet.Configs;
|
|||||||
using BenchmarkDotNet.Jobs;
|
using BenchmarkDotNet.Jobs;
|
||||||
using BepInEx;
|
using BepInEx;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using Reactor.Extensions;
|
using Reactor.Utilities;
|
||||||
|
using Reactor.Utilities.Extensions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Benchmarks;
|
namespace Reactor.Benchmarks;
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ using HarmonyLib;
|
|||||||
using Il2CppInterop.Runtime.Attributes;
|
using Il2CppInterop.Runtime.Attributes;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
using Reactor.Extensions;
|
using Reactor.Utilities.Attributes;
|
||||||
|
using Reactor.Utilities.ImGui;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Debugger;
|
namespace Reactor.Debugger;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
|
using Reactor.Utilities;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Debugger;
|
namespace Reactor.Debugger;
|
||||||
|
|||||||
@@ -2,9 +2,12 @@
|
|||||||
using BepInEx;
|
using BepInEx;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using Il2CppInterop.Runtime.Attributes;
|
using Il2CppInterop.Runtime.Attributes;
|
||||||
using Reactor.Extensions;
|
|
||||||
using Reactor.Networking;
|
using Reactor.Networking;
|
||||||
using Reactor.Networking.MethodRpc;
|
using Reactor.Networking.Attributes;
|
||||||
|
using Reactor.Networking.Rpc;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
|
using Reactor.Utilities.ImGui;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Random = UnityEngine.Random;
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
using Reactor.Networking;
|
using Reactor.Networking.Attributes;
|
||||||
|
using Reactor.Networking.Rpc;
|
||||||
|
|
||||||
namespace Reactor.Example;
|
namespace Reactor.Example;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Example", "Reactor.
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Benchmarks", "Reactor.Benchmarks\Reactor.Benchmarks.csproj", "{99B87307-3AEB-4A6A-BF45-871768308FDD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Benchmarks", "Reactor.Benchmarks\Reactor.Benchmarks.csproj", "{99B87307-3AEB-4A6A-BF45-871768308FDD}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{4BBF0A80-F6E6-4FDD-ADD0-8CB4F28F88A4}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
AmongUs.props = AmongUs.props
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
nuget.config = nuget.config
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
|
namespace System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This attribute is required by the compiler for the "unmanaged" generic type constraint.
|
||||||
|
/// It should be generated automatically, but for whatever reason its not.
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("Do not use directly.", true)]
|
||||||
|
internal class IsUnmanagedAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using HarmonyLib;
|
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Events;
|
|
||||||
using UnityEngine.Networking;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
using Il2CppType = Il2CppInterop.Runtime.Il2CppType;
|
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// General utilities
|
|
||||||
/// </summary>
|
|
||||||
public static class Extensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a delegate to get one notification when a scene has loaded.
|
|
||||||
/// </summary>
|
|
||||||
public static void once_sceneLoaded(Action<Scene, LoadSceneMode> value)
|
|
||||||
{
|
|
||||||
UnityAction<Scene, LoadSceneMode>? unityAction = null;
|
|
||||||
|
|
||||||
unityAction = (Action<Scene, LoadSceneMode>) ((scene, loadMode) =>
|
|
||||||
{
|
|
||||||
SceneManager.remove_sceneLoaded(unityAction);
|
|
||||||
value.Invoke(scene, loadMode);
|
|
||||||
});
|
|
||||||
|
|
||||||
SceneManager.add_sceneLoaded(unityAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns random <typeparamref name="T"/> from <paramref name="input"/>
|
|
||||||
/// </summary>
|
|
||||||
public static T? Random<T>(this IEnumerable<T> input)
|
|
||||||
{
|
|
||||||
var list = input as IList<T> ?? input.ToList();
|
|
||||||
return list.Count == 0 ? default : list[UnityEngine.Random.Range(0, list.Count)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the color as a hexadecimal string in the format "RRGGBBAA".
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="color">The color to be converted.</param>
|
|
||||||
/// <returns>Hexadecimal string representing the color.</returns>
|
|
||||||
/// <remarks>https://docs.unity3d.com/ScriptReference/ColorUtility.ToHtmlStringRGBA.html</remarks>
|
|
||||||
public static string ToHtmlStringRGBA(this Color32 color)
|
|
||||||
{
|
|
||||||
return $"{color.r:X2}{color.g:X2}{color.b:X2}{color.a:X2}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ToHtmlStringRGBA(UnityEngine.Color32)"/>
|
|
||||||
public static string ToHtmlStringRGBA(this Color color)
|
|
||||||
{
|
|
||||||
return ((Color32) color).ToHtmlStringRGBA();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Fully read <paramref name="input"/> stream, can be used as workaround for il2cpp streams.
|
|
||||||
/// </summary>
|
|
||||||
public static byte[] ReadFully(this Stream input)
|
|
||||||
{
|
|
||||||
using (var ms = new MemoryStream())
|
|
||||||
{
|
|
||||||
input.CopyTo(ms);
|
|
||||||
return ms.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends <see cref="UnityWebRequest"/> and return task that finishes on <paramref name="request"/> completion.
|
|
||||||
/// </summary>
|
|
||||||
public static Task SendAsync(this UnityWebRequest request)
|
|
||||||
{
|
|
||||||
var task = new TaskCompletionSource<object?>();
|
|
||||||
|
|
||||||
request.Send().m_completeCallback = (Action<AsyncOperation>) (_ =>
|
|
||||||
{
|
|
||||||
task.SetResult(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return task.Task;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly int _outline = Shader.PropertyToID("_Outline");
|
|
||||||
private static readonly int _outlineColor = Shader.PropertyToID("_OutlineColor");
|
|
||||||
private static readonly int _addColor = Shader.PropertyToID("_AddColor");
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets color outline for renderers using default Among Us shader
|
|
||||||
/// </summary>
|
|
||||||
public static void SetOutline(this Renderer renderer, Color? color)
|
|
||||||
{
|
|
||||||
renderer.material.SetFloat(_outline, color.HasValue ? 1 : 0);
|
|
||||||
|
|
||||||
if (color.HasValue)
|
|
||||||
{
|
|
||||||
renderer.material.SetColor(_outlineColor, color.Value);
|
|
||||||
renderer.material.SetColor(_addColor, color.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<MethodBase> GetMethods(this Type type, BindingFlags bindingAttr, Type returnType, params Type[] parameterTypes)
|
|
||||||
{
|
|
||||||
return type.GetMethods(bindingAttr).Where(x => x.ReturnType == returnType && x.GetParameters().Select(x => x.ParameterType).SequenceEqual(parameterTypes));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<MethodBase> GetMethods(this Type type, Type returnType, params Type[] parameterTypes)
|
|
||||||
{
|
|
||||||
return type.GetMethods(AccessTools.all, returnType, parameterTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T? LoadAsset<T>(this AssetBundle assetBundle, string name) where T : UnityEngine.Object
|
|
||||||
{
|
|
||||||
return assetBundle.LoadAsset(name, Il2CppType.Of<T>())?.Cast<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static unsafe Span<T> ToSpan<T>(this Il2CppStructArray<T> array) where T : unmanaged
|
|
||||||
{
|
|
||||||
return new Span<T>(IntPtr.Add(array.Pointer, IntPtr.Size * 4).ToPointer(), array.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.EventSystems;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GUI utilities
|
|
||||||
/// </summary>
|
|
||||||
public static class GUIExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Shortcut for empty texture
|
|
||||||
/// </summary>
|
|
||||||
public static Texture2D CreateEmptyTexture(int width = 0, int height = 0)
|
|
||||||
{
|
|
||||||
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clamp Rect to screen size
|
|
||||||
/// </summary>
|
|
||||||
public static Rect ClampScreen(this Rect rect)
|
|
||||||
{
|
|
||||||
rect.x = Mathf.Clamp(rect.x, 0, Screen.width - rect.width);
|
|
||||||
rect.y = Mathf.Clamp(rect.y, 0, Screen.height - rect.height);
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reset Rect size
|
|
||||||
/// </summary>
|
|
||||||
public static Rect ResetSize(this Rect rect)
|
|
||||||
{
|
|
||||||
rect.width = rect.height = 0;
|
|
||||||
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create <see cref="Sprite"/> from <paramref name="tex"/>
|
|
||||||
/// </summary>
|
|
||||||
public static Sprite CreateSprite(this Texture2D tex)
|
|
||||||
{
|
|
||||||
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DefaultControls.Resources StandardResources { get; internal set; } = null!;
|
|
||||||
|
|
||||||
public static GameObject CreateCanvas()
|
|
||||||
{
|
|
||||||
var gameObject = new GameObject("Canvas");
|
|
||||||
var canvas = gameObject.AddComponent<Canvas>();
|
|
||||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
|
||||||
|
|
||||||
var canvasScaler = gameObject.AddComponent<CanvasScaler>();
|
|
||||||
|
|
||||||
canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
|
|
||||||
canvasScaler.referencePixelsPerUnit = 100f;
|
|
||||||
|
|
||||||
gameObject.AddComponent<GraphicRaycaster>();
|
|
||||||
|
|
||||||
return gameObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static GameObject CreateEventSystem()
|
|
||||||
{
|
|
||||||
var gameObject = new GameObject("EventSystem");
|
|
||||||
gameObject.AddComponent<EventSystem>();
|
|
||||||
gameObject.AddComponent<StandaloneInputModule>();
|
|
||||||
gameObject.AddComponent<BaseInput>();
|
|
||||||
|
|
||||||
return gameObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetSize(this RectTransform rectTransform, float width, float height)
|
|
||||||
{
|
|
||||||
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
|
|
||||||
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Window
|
|
||||||
{
|
|
||||||
private static int _lastWindowId;
|
|
||||||
|
|
||||||
public static int NextWindowId()
|
|
||||||
{
|
|
||||||
return _lastWindowId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int Id { get; set; } = NextWindowId();
|
|
||||||
|
|
||||||
public bool Enabled { get; set; } = true;
|
|
||||||
public Rect Rect { get; set; }
|
|
||||||
public Action<int> Func { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
|
|
||||||
public Window(Rect rect, string title, Action<int> func)
|
|
||||||
{
|
|
||||||
Rect = rect;
|
|
||||||
Title = title;
|
|
||||||
Func = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Window(Rect rect, string title, Action func) : this(rect, title, id => func())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnGUI()
|
|
||||||
{
|
|
||||||
if (Enabled)
|
|
||||||
{
|
|
||||||
if (Event.current.type == EventType.Layout)
|
|
||||||
{
|
|
||||||
Rect = Rect.ResetSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect = GUILayout.Window(Id, Rect, Func, Title);
|
|
||||||
|
|
||||||
if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)) && Rect.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)))
|
|
||||||
{
|
|
||||||
Input.ResetInputAxes();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DragWindow : Window
|
|
||||||
{
|
|
||||||
public DragWindow(Rect rect, string title, Action<int> func) : base(rect, title, func)
|
|
||||||
{
|
|
||||||
Func = id =>
|
|
||||||
{
|
|
||||||
func(id);
|
|
||||||
|
|
||||||
GUI.DragWindow(new Rect(0, 0, 10000, 20));
|
|
||||||
Rect = Rect.ClampScreen();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public DragWindow(Rect rect, string title, Action func) : this(rect, title, id => func())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using Il2CppInterop.Runtime.Attributes;
|
|
||||||
using Il2CppInterop.Runtime.Injection;
|
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
|
||||||
|
|
||||||
[RegisterInIl2Cpp]
|
|
||||||
public class StreamWrapper : Il2CppSystem.IO.Stream
|
|
||||||
{
|
|
||||||
private readonly Stream _stream;
|
|
||||||
|
|
||||||
#pragma warning disable 8618
|
|
||||||
public StreamWrapper(IntPtr ptr) : base(ptr) { }
|
|
||||||
#pragma warning restore 8618
|
|
||||||
|
|
||||||
public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer<StreamWrapper>())
|
|
||||||
{
|
|
||||||
ClassInjector.DerivedConstructorBody(this);
|
|
||||||
_stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HideFromIl2Cpp]
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
private static unsafe Span<byte> GetSpan(Il2CppStructArray<byte> buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
var rawBuffer = (byte*) buffer.Pointer + 4 * IntPtr.Size;
|
|
||||||
return new Span<byte>(rawBuffer + offset, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Read(Il2CppStructArray<byte> buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
return _stream.Read(GetSpan(buffer, offset, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(Il2CppStructArray<byte> buffer, int offset, int count)
|
|
||||||
{
|
|
||||||
_stream.Write(GetSpan(buffer, offset, count));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Flush()
|
|
||||||
{
|
|
||||||
_stream.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Close()
|
|
||||||
{
|
|
||||||
_stream.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Dispose()
|
|
||||||
{
|
|
||||||
_stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override long Seek(long offset, Il2CppSystem.IO.SeekOrigin origin)
|
|
||||||
{
|
|
||||||
return _stream.Seek(offset, origin switch
|
|
||||||
{
|
|
||||||
Il2CppSystem.IO.SeekOrigin.Begin => SeekOrigin.Begin,
|
|
||||||
Il2CppSystem.IO.SeekOrigin.Current => SeekOrigin.Current,
|
|
||||||
Il2CppSystem.IO.SeekOrigin.End => SeekOrigin.End,
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(origin), origin, null),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetLength(long value)
|
|
||||||
{
|
|
||||||
_stream.SetLength(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanRead => _stream.CanRead;
|
|
||||||
public override bool CanSeek => _stream.CanSeek;
|
|
||||||
public override bool CanWrite => _stream.CanWrite;
|
|
||||||
public override long Length => _stream.Length;
|
|
||||||
|
|
||||||
public override long Position
|
|
||||||
{
|
|
||||||
get => _stream.Position;
|
|
||||||
set => _stream.Position = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StreamExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Wraps a System Stream into an Il2Cpp Stream
|
|
||||||
/// </summary>
|
|
||||||
public static StreamWrapper AsIl2Cpp(this Stream stream) => new(stream);
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ using System.Linq;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Localization;
|
||||||
|
|
||||||
public class CustomStringName
|
public class CustomStringName
|
||||||
{
|
{
|
||||||
+8
-1
@@ -1,15 +1,22 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
using Reactor.Networking.Serialization;
|
||||||
|
|
||||||
namespace Reactor.Networking.Serialization;
|
namespace Reactor.Networking.Attributes;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class MessageConverterAttribute : Attribute
|
public class MessageConverterAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<Assembly> _registeredAssemblies = new();
|
||||||
|
|
||||||
public static void Register(Assembly assembly)
|
public static void Register(Assembly assembly)
|
||||||
{
|
{
|
||||||
|
if (_registeredAssemblies.Contains(assembly)) return;
|
||||||
|
_registeredAssemblies.Add(assembly);
|
||||||
|
|
||||||
foreach (var type in assembly.GetTypes())
|
foreach (var type in assembly.GetTypes())
|
||||||
{
|
{
|
||||||
var attribute = type.GetCustomAttribute<MessageConverterAttribute>();
|
var attribute = type.GetCustomAttribute<MessageConverterAttribute>();
|
||||||
+9
-1
@@ -1,15 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
|
using Reactor.Networking.Rpc;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
|
||||||
namespace Reactor.Networking.MethodRpc;
|
namespace Reactor.Networking.Attributes;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class MethodRpcAttribute : Attribute
|
public class MethodRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<Assembly> _registeredAssemblies = new();
|
||||||
|
|
||||||
public uint Id { get; }
|
public uint Id { get; }
|
||||||
public SendOption Option { get; set; } = SendOption.Reliable;
|
public SendOption Option { get; set; } = SendOption.Reliable;
|
||||||
public RpcLocalHandling LocalHandling { get; set; } = RpcLocalHandling.Before;
|
public RpcLocalHandling LocalHandling { get; set; } = RpcLocalHandling.Before;
|
||||||
@@ -22,6 +27,9 @@ public class MethodRpcAttribute : Attribute
|
|||||||
|
|
||||||
public static void Register(Assembly assembly, BasePlugin plugin)
|
public static void Register(Assembly assembly, BasePlugin plugin)
|
||||||
{
|
{
|
||||||
|
if (_registeredAssemblies.Contains(assembly)) return;
|
||||||
|
_registeredAssemblies.Add(assembly);
|
||||||
|
|
||||||
var methods = assembly.GetTypes()
|
var methods = assembly.GetTypes()
|
||||||
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
|
.SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
|
||||||
|
|
||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Reactor.Networking;
|
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Networking.Attributes;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class ReactorModFlagsAttribute : Attribute
|
public class ReactorModFlagsAttribute : Attribute
|
||||||
@@ -24,7 +23,7 @@ public class ReactorModFlagsAttribute : Attribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
var metadataAttribute = type.Assembly.GetCustomAttributes<AssemblyMetadataAttribute>().SingleOrDefault(x => x.Key == "Reactor.ModFlags");
|
var metadataAttribute = type.Assembly.GetCustomAttributes<AssemblyMetadataAttribute>().SingleOrDefault(x => x.Key == "Reactor.ModFlags");
|
||||||
if (metadataAttribute != null && metadataAttribute.Value != null)
|
if (metadataAttribute is { Value: not null })
|
||||||
{
|
{
|
||||||
return Enum.Parse<ModFlags>(metadataAttribute.Value);
|
return Enum.Parse<ModFlags>(metadataAttribute.Value);
|
||||||
}
|
}
|
||||||
+14
-2
@@ -1,10 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Reactor.Networking;
|
using Reactor.Networking.Rpc;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Networking.Attributes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Utility attribute for automatically registering CustomRpc
|
/// Utility attribute for automatically registering CustomRpc
|
||||||
@@ -12,6 +14,8 @@ namespace Reactor;
|
|||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class RegisterCustomRpcAttribute : Attribute
|
public class RegisterCustomRpcAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<Assembly> _registeredAssemblies = new();
|
||||||
|
|
||||||
public uint Id { get; }
|
public uint Id { get; }
|
||||||
|
|
||||||
public RegisterCustomRpcAttribute(uint id)
|
public RegisterCustomRpcAttribute(uint id)
|
||||||
@@ -19,8 +23,16 @@ public class RegisterCustomRpcAttribute : Attribute
|
|||||||
Id = id;
|
Id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers all types marked with <see cref="RegisterCustomRpcAttribute"/> from the specified assembly as custom rpcs
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assembly"></param>
|
||||||
|
/// <param name="plugin"></param>
|
||||||
public static void Register(Assembly assembly, BasePlugin plugin)
|
public static void Register(Assembly assembly, BasePlugin plugin)
|
||||||
{
|
{
|
||||||
|
if (_registeredAssemblies.Contains(assembly)) return;
|
||||||
|
_registeredAssemblies.Add(assembly);
|
||||||
|
|
||||||
foreach (var type in assembly.GetTypes())
|
foreach (var type in assembly.GetTypes())
|
||||||
{
|
{
|
||||||
var attribute = type.GetCustomAttribute<RegisterCustomRpcAttribute>();
|
var attribute = type.GetCustomAttribute<RegisterCustomRpcAttribute>();
|
||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Extensions;
|
||||||
|
|
||||||
public static class Extensions
|
public static class ClientExtensions
|
||||||
{
|
{
|
||||||
public static void KickWithReason(this InnerNetClient innerNetClient, int targetClientId, string reason)
|
public static void KickWithReason(this InnerNetClient innerNetClient, int targetClientId, string reason)
|
||||||
{
|
{
|
||||||
+1
-1
@@ -3,7 +3,7 @@ using Hazel;
|
|||||||
using Hazel.Udp;
|
using Hazel.Udp;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
namespace Reactor.Networking.Extensions;
|
||||||
|
|
||||||
public static class ExtraMessageExtensions
|
public static class ExtraMessageExtensions
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Messages;
|
||||||
|
|
||||||
internal static class ModdedHandshakeC2S
|
internal static class ModdedHandshakeC2S
|
||||||
{
|
{
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Messages;
|
||||||
|
|
||||||
internal static class ModdedHandshakeS2C
|
internal static class ModdedHandshakeS2C
|
||||||
{
|
{
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Messages;
|
||||||
|
|
||||||
public static class ReactorHeader
|
internal static class ReactorHeader
|
||||||
{
|
{
|
||||||
private const ulong MAGIC = 0x72656163746f72; // "reactor" in ascii, 7 bytes
|
private const ulong MAGIC = 0x72656163746f72; // "reactor" in ascii, 7 bytes
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ using System.Text;
|
|||||||
using BepInEx;
|
using BepInEx;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
|
using Reactor.Networking.Attributes;
|
||||||
using Reactor.Networking.Patches;
|
using Reactor.Networking.Patches;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking;
|
||||||
@@ -13,31 +14,31 @@ public static class ModList
|
|||||||
{
|
{
|
||||||
public static IReadOnlyCollection<Mod> Current { get; private set; } = null!;
|
public static IReadOnlyCollection<Mod> Current { get; private set; } = null!;
|
||||||
|
|
||||||
private static readonly Dictionary<string, Mod> _mapById = new();
|
private static readonly Dictionary<string, Mod> _modById = new();
|
||||||
private static readonly Dictionary<Type, Mod> _mapByPluginType = new();
|
private static readonly Dictionary<Type, Mod> _modByPluginType = new();
|
||||||
|
|
||||||
public static Mod GetById(string id)
|
public static Mod GetById(string id)
|
||||||
{
|
{
|
||||||
return _mapById[id];
|
return _modById[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Mod GetByPluginType(Type pluginType)
|
internal static Mod GetByPluginType(Type pluginType)
|
||||||
{
|
{
|
||||||
return _mapByPluginType[pluginType];
|
return _modByPluginType[pluginType];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly Dictionary<uint, Mod> _mapByNetId = new();
|
private static readonly Dictionary<uint, Mod> _modByNetId = new();
|
||||||
private static readonly Dictionary<Mod, uint> _netIdMap = new();
|
private static readonly Dictionary<Mod, uint> _netIdByMod = new();
|
||||||
|
|
||||||
internal static Mod GetByNetId(uint netId)
|
internal static Mod GetByNetId(uint netId)
|
||||||
{
|
{
|
||||||
return _mapByNetId[netId];
|
return _modByNetId[netId];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static uint GetNetId(this Mod mod)
|
internal static uint GetNetId(this Mod mod)
|
||||||
{
|
{
|
||||||
if (!mod.IsRequiredOnAllClients) throw new ArgumentException("Cannot get a net id for a mod without RequireOnAllClients flag", nameof(mod));
|
if (!mod.IsRequiredOnAllClients) throw new ArgumentException("Cannot get a net id for a mod without RequireOnAllClients flag", nameof(mod));
|
||||||
return _netIdMap[mod];
|
return _netIdByMod[mod];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mod ReadMod(this MessageReader reader)
|
public static Mod ReadMod(this MessageReader reader)
|
||||||
@@ -75,16 +76,16 @@ public static class ModList
|
|||||||
.ThenBy(x => x.Id, StringComparer.Ordinal)
|
.ThenBy(x => x.Id, StringComparer.Ordinal)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
|
|
||||||
_mapByNetId.Clear();
|
_modByNetId.Clear();
|
||||||
_netIdMap.Clear();
|
_netIdByMod.Clear();
|
||||||
|
|
||||||
uint netId = 1;
|
uint netId = 1;
|
||||||
foreach (var mod in Current)
|
foreach (var mod in Current)
|
||||||
{
|
{
|
||||||
if (!mod.IsRequiredOnAllClients) continue;
|
if (!mod.IsRequiredOnAllClients) continue;
|
||||||
|
|
||||||
_mapByNetId[netId] = mod;
|
_modByNetId[netId] = mod;
|
||||||
_netIdMap[mod] = netId;
|
_netIdByMod[mod] = netId;
|
||||||
netId++;
|
netId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +111,8 @@ public static class ModList
|
|||||||
pluginInfo.Metadata.Name
|
pluginInfo.Metadata.Name
|
||||||
);
|
);
|
||||||
|
|
||||||
_mapById[mod.Id] = mod;
|
_modById[mod.Id] = mod;
|
||||||
_mapByPluginType[pluginType] = mod;
|
_modByPluginType[pluginType] = mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void Initialize()
|
internal static void Initialize()
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
using Il2CppInterop.Runtime;
|
using Il2CppInterop.Runtime;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
using Reactor.Networking.Extensions;
|
||||||
|
using Reactor.Networking.Messages;
|
||||||
|
using Reactor.Networking.Serialization;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Networking.Patches;
|
namespace Reactor.Networking.Patches;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using BepInEx.Unity.IL2CPP;
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
public abstract class CustomRpc<TPlugin, TInnerNetObject, TData> : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
|
public abstract class CustomRpc<TPlugin, TInnerNetObject, TData> : UnsafeCustomRpc where TPlugin : BasePlugin where TInnerNetObject : InnerNetObject
|
||||||
{
|
{
|
||||||
+13
-47
@@ -6,22 +6,16 @@ using HarmonyLib;
|
|||||||
using Hazel;
|
using Hazel;
|
||||||
using Il2CppInterop.Generator.Extensions;
|
using Il2CppInterop.Generator.Extensions;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
public enum RpcLocalHandling
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Before,
|
|
||||||
After,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CustomRpcManager
|
public class CustomRpcManager
|
||||||
{
|
{
|
||||||
public const byte CallId = byte.MaxValue;
|
public const byte CallId = byte.MaxValue;
|
||||||
|
|
||||||
private readonly List<UnsafeCustomRpc> _list = new();
|
private readonly List<UnsafeCustomRpc> _list = new();
|
||||||
private readonly Dictionary<Type, Dictionary<Mod, Dictionary<uint, UnsafeCustomRpc>>> _map = new();
|
internal readonly Dictionary<Type, Dictionary<Mod, Dictionary<uint, UnsafeCustomRpc>>> _map = new();
|
||||||
|
|
||||||
public IReadOnlyList<UnsafeCustomRpc> List => _list.AsReadOnly();
|
public IReadOnlyList<UnsafeCustomRpc> List => _list.AsReadOnly();
|
||||||
|
|
||||||
@@ -29,8 +23,8 @@ public class CustomRpcManager
|
|||||||
{
|
{
|
||||||
customRpc.Manager = this;
|
customRpc.Manager = this;
|
||||||
_list.Add(customRpc);
|
_list.Add(customRpc);
|
||||||
_map.GetOrCreate(customRpc.InnerNetObjectType, _ => new Dictionary<Mod, Dictionary<uint, UnsafeCustomRpc>>())
|
_map.GetOrCreate(customRpc.InnerNetObjectType, static _ => new Dictionary<Mod, Dictionary<uint, UnsafeCustomRpc>>())
|
||||||
.GetOrCreate(customRpc.Mod, _ => new Dictionary<uint, UnsafeCustomRpc>())
|
.GetOrCreate(customRpc.Mod, static _ => new Dictionary<uint, UnsafeCustomRpc>())
|
||||||
.Add(customRpc.Id, customRpc);
|
.Add(customRpc.Id, customRpc);
|
||||||
|
|
||||||
if (customRpc.IsSingleton)
|
if (customRpc.IsSingleton)
|
||||||
@@ -41,22 +35,6 @@ public class CustomRpcManager
|
|||||||
return customRpc;
|
return customRpc;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPatch]
|
|
||||||
private static class HandleRpcPatch
|
|
||||||
{
|
|
||||||
internal static List<Type> InnerNetObjectTypes { get; } = typeof(InnerNetObject).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(InnerNetObject)) && x != typeof(LobbyBehaviour)).ToList();
|
|
||||||
|
|
||||||
public static IEnumerable<MethodBase> TargetMethods()
|
|
||||||
{
|
|
||||||
return InnerNetObjectTypes.Select(x => x.GetMethod(nameof(InnerNetObject.HandleRpc), AccessTools.allDeclared)).Where(m => m != null)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Prefix(InnerNetObject __instance, [HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] MessageReader reader)
|
|
||||||
{
|
|
||||||
return !HandleRpc(__instance, callId, reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HandleRpc(InnerNetObject innerNetObject, byte callId, MessageReader reader)
|
public static bool HandleRpc(InnerNetObject innerNetObject, byte callId, MessageReader reader)
|
||||||
{
|
{
|
||||||
if (callId == CallId)
|
if (callId == CallId)
|
||||||
@@ -76,32 +54,20 @@ public class CustomRpcManager
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static class Rpc<T> where T : UnsafeCustomRpc
|
[HarmonyPatch]
|
||||||
{
|
internal static class HandleRpcPatch
|
||||||
private static T? _instance;
|
|
||||||
|
|
||||||
public static T Instance
|
|
||||||
{
|
{
|
||||||
get
|
private static List<Type> InnerNetObjectTypes { get; } = typeof(InnerNetObject).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(InnerNetObject)) && x != typeof(LobbyBehaviour)).ToList();
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
throw new Exception($"{typeof(T).FullName} isn't registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
public static IEnumerable<MethodBase> TargetMethods()
|
||||||
|
{
|
||||||
|
return InnerNetObjectTypes.Select(x => x.GetMethod(nameof(InnerNetObject.HandleRpc), AccessTools.allDeclared)).Where(m => m != null)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal set
|
public static bool Prefix(InnerNetObject __instance, [HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] MessageReader reader)
|
||||||
{
|
{
|
||||||
if (_instance != null)
|
return !HandleRpc(__instance, callId, reader);
|
||||||
{
|
|
||||||
throw new Exception($"{typeof(T).FullName} is already registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
_instance = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,9 @@ using InnerNet;
|
|||||||
using MonoMod.RuntimeDetour;
|
using MonoMod.RuntimeDetour;
|
||||||
using MonoMod.Utils;
|
using MonoMod.Utils;
|
||||||
using Reactor.Networking.Serialization;
|
using Reactor.Networking.Serialization;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
|
||||||
namespace Reactor.Networking.MethodRpc;
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
public class MethodRpc : UnsafeCustomRpc
|
public class MethodRpc : UnsafeCustomRpc
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
public abstract class PlayerCustomRpc<TPlugin, TData> : CustomRpc<TPlugin, PlayerControl, TData> where TPlugin : BasePlugin
|
public abstract class PlayerCustomRpc<TPlugin, TData> : CustomRpc<TPlugin, PlayerControl, TData> where TPlugin : BasePlugin
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
|
public static class Rpc<T> where T : UnsafeCustomRpc
|
||||||
|
{
|
||||||
|
private static T? _instance;
|
||||||
|
|
||||||
|
public static T Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"{typeof(T).FullName} isn't registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal set
|
||||||
|
{
|
||||||
|
if (_instance != null)
|
||||||
|
{
|
||||||
|
throw new Exception($"{typeof(T).FullName} is already registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
_instance = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
|
public enum RpcLocalHandling
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Before,
|
||||||
|
After,
|
||||||
|
}
|
||||||
@@ -6,9 +6,10 @@ using Hazel;
|
|||||||
using Hazel.Udp;
|
using Hazel.Udp;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
using Reactor.Utilities;
|
||||||
using Buffer = Il2CppSystem.Buffer;
|
using Buffer = Il2CppSystem.Buffer;
|
||||||
|
|
||||||
namespace Reactor.Networking;
|
namespace Reactor.Networking.Rpc;
|
||||||
|
|
||||||
public abstract class UnsafeCustomRpc
|
public abstract class UnsafeCustomRpc
|
||||||
{
|
{
|
||||||
@@ -4,6 +4,7 @@ using System.Reflection;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
using Reactor.Networking.Attributes;
|
||||||
|
|
||||||
namespace Reactor.Networking.Serialization;
|
namespace Reactor.Networking.Serialization;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Hazel;
|
using Hazel;
|
||||||
using Reactor.Extensions;
|
using Reactor.Networking.Extensions;
|
||||||
|
using Reactor.Networking.Rpc;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Networking.Serialization;
|
namespace Reactor.Networking.Serialization;
|
||||||
@@ -83,7 +84,7 @@ public static class MessageSerializer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object[] Deserialize(MessageReader reader, MethodRpc.MethodRpc methodRpc)
|
public static object[] Deserialize(MessageReader reader, MethodRpc methodRpc)
|
||||||
{
|
{
|
||||||
var parameters = methodRpc.Method.GetParameters();
|
var parameters = methodRpc.Method.GetParameters();
|
||||||
var args = new object[parameters.Length - 1];
|
var args = new object[parameters.Length - 1];
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using HarmonyLib;
|
|
||||||
using InnerNet;
|
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
|
||||||
|
|
||||||
internal static class BetterGuestPatch
|
|
||||||
{
|
|
||||||
[HarmonyPatch(typeof(SaveManager), nameof(SaveManager.ChatModeType), MethodType.Getter)]
|
|
||||||
public static class ChatModeTypePatch
|
|
||||||
{
|
|
||||||
public static bool Prefix(out QuickChatModes __result)
|
|
||||||
{
|
|
||||||
__result = QuickChatModes.FreeChatOrQuickChat;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@ using HarmonyLib;
|
|||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Patches.Fixes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// "Fixes" an issue where empty TextBoxes have wrong cursor positions
|
/// "Fixes" an issue where empty TextBoxes have wrong cursor positions
|
||||||
+12
-12
@@ -5,24 +5,24 @@ using System.Net.Sockets;
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using InnerNet;
|
using InnerNet;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Patches.Fixes;
|
||||||
|
|
||||||
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.Connect))]
|
[HarmonyPatch]
|
||||||
public static class ConnectPatch
|
internal static class ServerInfoFixesPatch
|
||||||
{
|
{
|
||||||
public static void Prefix(InnerNetClient __instance)
|
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.Connect))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
public static void LogConnect(InnerNetClient __instance)
|
||||||
{
|
{
|
||||||
Info($"Joining {__instance.networkAddress}:{__instance.networkPort}");
|
Info($"Joining {__instance.networkAddress}:{__instance.networkPort}");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fixes hardcoded port and filters out IPv6 in DnsRegionInfo
|
/// Fixes hardcoded port and filters out IPv6 in DnsRegionInfo
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HarmonyPatch(typeof(DnsRegionInfo), nameof(DnsRegionInfo.PopulateServers))]
|
[HarmonyPatch(typeof(DnsRegionInfo), nameof(DnsRegionInfo.PopulateServers))]
|
||||||
public static class PopulateServersPatch
|
[HarmonyPrefix]
|
||||||
{
|
public static bool FixPopulateServers(DnsRegionInfo __instance)
|
||||||
public static bool Prefix(DnsRegionInfo __instance)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Patches.Miscellaneous;
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
internal static class CustomServersPatch
|
internal static class CustomServersPatch
|
||||||
@@ -8,7 +8,7 @@ internal static class CustomServersPatch
|
|||||||
[HarmonyPatch(typeof(AuthManager._CoConnect_d__4), nameof(AuthManager._CoConnect_d__4.MoveNext))]
|
[HarmonyPatch(typeof(AuthManager._CoConnect_d__4), nameof(AuthManager._CoConnect_d__4.MoveNext))]
|
||||||
[HarmonyPatch(typeof(AuthManager._CoWaitForNonce_d__6), nameof(AuthManager._CoWaitForNonce_d__6.MoveNext))]
|
[HarmonyPatch(typeof(AuthManager._CoWaitForNonce_d__6), nameof(AuthManager._CoWaitForNonce_d__6.MoveNext))]
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static bool DisableAuthServerPatch(out bool __result)
|
public static bool DisableAuthServer(out bool __result)
|
||||||
{
|
{
|
||||||
__result = false;
|
__result = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -16,7 +16,7 @@ internal static class CustomServersPatch
|
|||||||
|
|
||||||
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__1), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__1.MoveNext))]
|
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__1), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__1.MoveNext))]
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
public static void EnableUdpMatchmakingPatch(AmongUsClient._CoJoinOnlinePublicGame_d__1 __instance)
|
public static void EnableUdpMatchmaking(AmongUsClient._CoJoinOnlinePublicGame_d__1 __instance)
|
||||||
{
|
{
|
||||||
// Skip to state 1 which just calls CoJoinOnlineGameDirect
|
// Skip to state 1 which just calls CoJoinOnlineGameDirect
|
||||||
if (__instance.__1__state == 0 && !ServerManager.Instance.IsHttp)
|
if (__instance.__1__state == 0 && !ServerManager.Instance.IsHttp)
|
||||||
@@ -7,17 +7,16 @@ using UnityEngine;
|
|||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Patches.Miscellaneous;
|
||||||
|
|
||||||
public static class FreeNamePatch
|
[HarmonyPatch]
|
||||||
|
internal static class FreeNamePatch
|
||||||
{
|
{
|
||||||
[HarmonyPatch(typeof(AccountManager), nameof(AccountManager.CheckAndRegenerateName))]
|
[HarmonyPatch(typeof(AccountManager), nameof(AccountManager.CheckAndRegenerateName))]
|
||||||
internal static class ValidateRandomNamePatch
|
[HarmonyPrefix]
|
||||||
|
public static bool DontRegenerateNames()
|
||||||
{
|
{
|
||||||
public static bool Prefix()
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Patches.Miscellaneous;
|
||||||
|
|
||||||
[HarmonyPatch(typeof(SplashManager), nameof(SplashManager.Start))]
|
[HarmonyPatch]
|
||||||
internal static class SplashSkip
|
internal static class SplashSkipPatch
|
||||||
{
|
|
||||||
private static void Prefix(SplashManager __instance)
|
|
||||||
{
|
|
||||||
__instance.minimumSecondsBeforeSceneChange = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(SplashManager), nameof(SplashManager.Update))]
|
|
||||||
internal static class WaitForEpicAuth
|
|
||||||
{
|
{
|
||||||
private static readonly PropertyInfo? _localUserIdProperty = typeof(EpicManager).GetProperty("localUserId", BindingFlags.Static | BindingFlags.Public);
|
private static readonly PropertyInfo? _localUserIdProperty = typeof(EpicManager).GetProperty("localUserId", BindingFlags.Static | BindingFlags.Public);
|
||||||
private static bool _loginFinished;
|
private static bool _loginFinished;
|
||||||
|
|
||||||
private static bool Prefix(SplashManager __instance)
|
[HarmonyPatch(typeof(SplashManager), nameof(SplashManager.Start))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static void RemoveMinimumWait(SplashManager __instance)
|
||||||
|
{
|
||||||
|
__instance.minimumSecondsBeforeSceneChange = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(SplashManager), nameof(SplashManager.Update))]
|
||||||
|
[HarmonyPrefix]
|
||||||
|
private static bool WaitForLogin(SplashManager __instance)
|
||||||
{
|
{
|
||||||
if (__instance.startedSceneLoad) return true;
|
if (__instance.startedSceneLoad) return true;
|
||||||
|
|
||||||
@@ -32,11 +32,9 @@ internal static class WaitForEpicAuth
|
|||||||
|
|
||||||
// EpicManager calls SaveManager.LoadPlayerPrefs(true) both on successful and unsuccessful EOS login
|
// EpicManager calls SaveManager.LoadPlayerPrefs(true) both on successful and unsuccessful EOS login
|
||||||
[HarmonyPatch(typeof(SaveManager), nameof(SaveManager.LoadPlayerPrefs))]
|
[HarmonyPatch(typeof(SaveManager), nameof(SaveManager.LoadPlayerPrefs))]
|
||||||
private static class LoadPlayerPrefsPatch
|
[HarmonyPostfix]
|
||||||
|
private static void WaitForEpicAuth(bool overrideLoad)
|
||||||
{
|
{
|
||||||
private static void Postfix(bool overrideLoad)
|
if (overrideLoad) _loginFinished = true;
|
||||||
{
|
|
||||||
if (overrideLoad) _loginFinished = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using HarmonyLib;
|
||||||
|
|
||||||
|
namespace Reactor.Patches.Miscellaneous;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows launching steam builds outside of steam
|
||||||
|
/// </summary>
|
||||||
|
[HarmonyPatch]
|
||||||
|
internal static class StandaloneSteamPatch
|
||||||
|
{
|
||||||
|
private static readonly Type? _type = Type.GetType("Steamworks.SteamAPI, Assembly-CSharp-firstpass", false);
|
||||||
|
|
||||||
|
[HarmonyPrepare]
|
||||||
|
public static bool Prepare()
|
||||||
|
{
|
||||||
|
return _type != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyTargetMethod]
|
||||||
|
public static MethodBase TargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method(_type, "RestartAppIfNecessary");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Prefix(out bool __result)
|
||||||
|
{
|
||||||
|
const string file = "steam_appid.txt";
|
||||||
|
|
||||||
|
if (!File.Exists(file))
|
||||||
|
{
|
||||||
|
File.WriteAllText(file, "945360");
|
||||||
|
}
|
||||||
|
|
||||||
|
return __result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
using System.Linq;
|
|
||||||
using HarmonyLib;
|
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
|
||||||
|
|
||||||
internal static class PlayerIdPatch
|
|
||||||
{
|
|
||||||
[HarmonyPatch(typeof(GameData), nameof(GameData.GetAvailableId))]
|
|
||||||
public static class GetAvailableIdPatch
|
|
||||||
{
|
|
||||||
public static bool Prefix(GameData __instance, out sbyte __result)
|
|
||||||
{
|
|
||||||
sbyte i = 0;
|
|
||||||
|
|
||||||
while (__instance.AllPlayers.ToArray().Any(p => p.PlayerId == i))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
__result = i;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ using System;
|
|||||||
using BepInEx;
|
using BepInEx;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Reactor.Extensions;
|
using Reactor.Utilities.Extensions;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using HarmonyLib;
|
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
|
||||||
|
|
||||||
internal static class SteamPatch
|
|
||||||
{
|
|
||||||
[HarmonyPatch]
|
|
||||||
public static class RestartAppIfNecessaryPatch
|
|
||||||
{
|
|
||||||
public const string TypeName = "Steamworks.SteamAPI, Assembly-CSharp-firstpass";
|
|
||||||
public const string MethodName = "RestartAppIfNecessary";
|
|
||||||
|
|
||||||
public static bool Prepare()
|
|
||||||
{
|
|
||||||
return Type.GetType(TypeName, false) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MethodBase TargetMethod()
|
|
||||||
{
|
|
||||||
return AccessTools.Method(TypeName + ":" + MethodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Prefix(out bool __result)
|
|
||||||
{
|
|
||||||
const string file = "steam_appid.txt";
|
|
||||||
|
|
||||||
if (!File.Exists(file))
|
|
||||||
{
|
|
||||||
File.WriteAllText(file, "945360");
|
|
||||||
}
|
|
||||||
|
|
||||||
return __result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
<Compile Include="..\Reactor.Networking.Shared\**\*.cs" LinkBase="Reactor.Networking.Shared" Visible="false" />
|
<Compile Include="..\Reactor.Networking.Shared\**\*.cs" LinkBase="Networking" Visible="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
global using static Reactor.Logger<Reactor.ReactorPlugin>;
|
global using static Reactor.Utilities.Logger<Reactor.ReactorPlugin>;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using BepInEx;
|
using BepInEx;
|
||||||
using BepInEx.Configuration;
|
using BepInEx.Configuration;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Reactor.Extensions;
|
|
||||||
using Reactor.Networking;
|
using Reactor.Networking;
|
||||||
using Reactor.Networking.MethodRpc;
|
|
||||||
using Reactor.Networking.Serialization;
|
|
||||||
using Reactor.Patches;
|
|
||||||
using Reactor.Unstrip;
|
|
||||||
using Il2CppInterop.Runtime.Attributes;
|
using Il2CppInterop.Runtime.Attributes;
|
||||||
|
using Reactor.Networking.Attributes;
|
||||||
|
using Reactor.Networking.Rpc;
|
||||||
|
using Reactor.Patches;
|
||||||
|
using Reactor.Patches.Miscellaneous;
|
||||||
|
using Reactor.Utilities;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ public partial class ReactorPlugin : BasePlugin
|
|||||||
public override bool Unload()
|
public override bool Unload()
|
||||||
{
|
{
|
||||||
Harmony.UnpatchSelf();
|
Harmony.UnpatchSelf();
|
||||||
RegionInfoWatcher?.Dispose();
|
RegionInfoWatcher.Dispose();
|
||||||
|
|
||||||
return base.Unload();
|
return base.Unload();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
// ReSharper disable CheckNamespace
|
|
||||||
|
|
||||||
namespace System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
public class IsUnmanagedAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -5,10 +5,10 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
using MonoMod.Utils;
|
using MonoMod.Utils;
|
||||||
using Reactor.Extensions;
|
using Reactor.Utilities.Extensions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
public static class AssetBundleManager
|
public static class AssetBundleManager
|
||||||
{
|
{
|
||||||
+14
-4
@@ -1,10 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Runtime.Injection;
|
using Il2CppInterop.Runtime.Injection;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities.Attributes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Utility attribute for automatically calling <see cref="ClassInjector.RegisterTypeInIl2Cpp{T}()"/>
|
/// Utility attribute for automatically calling <see cref="ClassInjector.RegisterTypeInIl2Cpp{T}()"/>
|
||||||
@@ -12,6 +13,8 @@ namespace Reactor;
|
|||||||
[AttributeUsage(AttributeTargets.Class)]
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
public class RegisterInIl2CppAttribute : Attribute
|
public class RegisterInIl2CppAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<Assembly> _registeredAssemblies = new();
|
||||||
|
|
||||||
public Type[] Interfaces { get; }
|
public Type[] Interfaces { get; }
|
||||||
|
|
||||||
public RegisterInIl2CppAttribute()
|
public RegisterInIl2CppAttribute()
|
||||||
@@ -24,12 +27,12 @@ public class RegisterInIl2CppAttribute : Attribute
|
|||||||
Interfaces = interfaces;
|
Interfaces = interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Register(Type type, Type[] interfaces)
|
private static void RegisterType(Type type, Type[] interfaces)
|
||||||
{
|
{
|
||||||
var baseTypeAttribute = type.BaseType?.GetCustomAttribute<RegisterInIl2CppAttribute>();
|
var baseTypeAttribute = type.BaseType?.GetCustomAttribute<RegisterInIl2CppAttribute>();
|
||||||
if (baseTypeAttribute != null)
|
if (baseTypeAttribute != null)
|
||||||
{
|
{
|
||||||
Register(type.BaseType!, baseTypeAttribute.Interfaces);
|
RegisterType(type.BaseType!, baseTypeAttribute.Interfaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ClassInjector.IsTypeRegisteredInIl2Cpp(type))
|
if (ClassInjector.IsTypeRegisteredInIl2Cpp(type))
|
||||||
@@ -47,14 +50,21 @@ public class RegisterInIl2CppAttribute : Attribute
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers in Il2Cpp all types marked with <see cref="RegisterInIl2CppAttribute"/> from the specified assembly.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assembly"></param>
|
||||||
public static void Register(Assembly assembly)
|
public static void Register(Assembly assembly)
|
||||||
{
|
{
|
||||||
|
if (_registeredAssemblies.Contains(assembly)) return;
|
||||||
|
_registeredAssemblies.Add(assembly);
|
||||||
|
|
||||||
foreach (var type in assembly.GetTypes())
|
foreach (var type in assembly.GetTypes())
|
||||||
{
|
{
|
||||||
var attribute = type.GetCustomAttribute<RegisterInIl2CppAttribute>();
|
var attribute = type.GetCustomAttribute<RegisterInIl2CppAttribute>();
|
||||||
if (attribute != null)
|
if (attribute != null)
|
||||||
{
|
{
|
||||||
Register(type, attribute.Interfaces);
|
RegisterType(type, attribute.Interfaces);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.EventSystems;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
|
public static class CanvasUtilities
|
||||||
|
{
|
||||||
|
public static GameObject CreateCanvas()
|
||||||
|
{
|
||||||
|
var gameObject = new GameObject("Canvas");
|
||||||
|
var canvas = gameObject.AddComponent<Canvas>();
|
||||||
|
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||||
|
|
||||||
|
var canvasScaler = gameObject.AddComponent<CanvasScaler>();
|
||||||
|
|
||||||
|
canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;
|
||||||
|
canvasScaler.referencePixelsPerUnit = 100f;
|
||||||
|
|
||||||
|
gameObject.AddComponent<GraphicRaycaster>();
|
||||||
|
|
||||||
|
return gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GameObject CreateEventSystem()
|
||||||
|
{
|
||||||
|
var gameObject = new GameObject("EventSystem");
|
||||||
|
gameObject.AddComponent<EventSystem>();
|
||||||
|
gameObject.AddComponent<StandaloneInputModule>();
|
||||||
|
gameObject.AddComponent<BaseInput>();
|
||||||
|
|
||||||
|
return gameObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shortcut for empty texture
|
||||||
|
/// </summary>
|
||||||
|
public static Texture2D CreateEmptyTexture(int width = 0, int height = 0)
|
||||||
|
{
|
||||||
|
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,10 @@ using System.Collections;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using BepInEx.Unity.IL2CPP.Utils;
|
using BepInEx.Unity.IL2CPP.Utils;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
public static class Coroutines
|
public static class Coroutines
|
||||||
{
|
{
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
using Reactor.Extensions;
|
using Reactor.Utilities.Extensions;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
namespace Reactor.Unstrip;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
internal static class DefaultBundle
|
public static class DefaultBundle
|
||||||
{
|
{
|
||||||
public static void Load()
|
public static DefaultControls.Resources StandardResources { get; internal set; } = null!;
|
||||||
|
|
||||||
|
internal static void Load()
|
||||||
{
|
{
|
||||||
var bundle = AssetBundleManager.Load("default");
|
var bundle = AssetBundleManager.Load("default");
|
||||||
|
|
||||||
@@ -17,7 +19,7 @@ internal static class DefaultBundle
|
|||||||
Graphic.defaultGraphicMaterial.shader = backupShader;
|
Graphic.defaultGraphicMaterial.shader = backupShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIExtensions.StandardResources = new DefaultControls.Resources
|
StandardResources = new DefaultControls.Resources
|
||||||
{
|
{
|
||||||
background = bundle.LoadAsset<Sprite>("Background")!.DontUnload(),
|
background = bundle.LoadAsset<Sprite>("Background")!.DontUnload(),
|
||||||
checkmark = bundle.LoadAsset<Sprite>("Checkmark")!.DontUnload(),
|
checkmark = bundle.LoadAsset<Sprite>("Checkmark")!.DontUnload(),
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Il2CppInterop.Runtime.Attributes;
|
using Il2CppInterop.Runtime.Attributes;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
[RegisterInIl2Cpp]
|
[RegisterInIl2Cpp]
|
||||||
public class Dispatcher : MonoBehaviour
|
public class Dispatcher : MonoBehaviour
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using Il2CppInterop.Runtime;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
|
public static class AssetBundleExtensions
|
||||||
|
{
|
||||||
|
public static T? LoadAsset<T>(this AssetBundle assetBundle, string name) where T : Object
|
||||||
|
{
|
||||||
|
return assetBundle.LoadAsset(name, Il2CppType.Of<T>())?.Cast<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GUI utilities
|
||||||
|
/// </summary>
|
||||||
|
public static class GUIExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Clamp Rect to screen size
|
||||||
|
/// </summary>
|
||||||
|
public static Rect ClampScreen(this Rect rect)
|
||||||
|
{
|
||||||
|
rect.x = Mathf.Clamp(rect.x, 0, Screen.width - rect.width);
|
||||||
|
rect.y = Mathf.Clamp(rect.y, 0, Screen.height - rect.height);
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset Rect size
|
||||||
|
/// </summary>
|
||||||
|
public static Rect ResetSize(this Rect rect)
|
||||||
|
{
|
||||||
|
rect.width = rect.height = 0;
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create <see cref="Sprite"/> from <paramref name="tex"/>
|
||||||
|
/// </summary>
|
||||||
|
public static Sprite CreateSprite(this Texture2D tex)
|
||||||
|
{
|
||||||
|
return Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetSize(this RectTransform rectTransform, float width, float height)
|
||||||
|
{
|
||||||
|
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
|
||||||
|
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
|
public static class Il2CppInteropExtensions
|
||||||
|
{
|
||||||
|
public static unsafe Span<T> ToSpan<T>(this Il2CppStructArray<T> array) where T : unmanaged
|
||||||
|
{
|
||||||
|
return new Span<T>(IntPtr.Add(array.Pointer, IntPtr.Size * 4).ToPointer(), array.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-1
@@ -2,7 +2,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
public static class RandomExtensions
|
public static class RandomExtensions
|
||||||
{
|
{
|
||||||
@@ -20,4 +20,13 @@ public static class RandomExtensions
|
|||||||
{
|
{
|
||||||
return random.NextDouble() * (maxValue - minValue) + minValue;
|
return random.NextDouble() * (maxValue - minValue) + minValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns random <typeparamref name="T"/> from <paramref name="input"/>
|
||||||
|
/// </summary>
|
||||||
|
public static T? Random<T>(this IEnumerable<T> input)
|
||||||
|
{
|
||||||
|
var list = input as IList<T> ?? input.ToList();
|
||||||
|
return list.Count == 0 ? default : list[UnityEngine.Random.Range(0, list.Count)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+13
-1
@@ -1,4 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Il2CppInterop.Common;
|
using Il2CppInterop.Common;
|
||||||
@@ -10,7 +12,7 @@ using MethodInfo = System.Reflection.MethodInfo;
|
|||||||
using Il2CppMethodInfo = Il2CppSystem.Reflection.MethodInfo;
|
using Il2CppMethodInfo = Il2CppSystem.Reflection.MethodInfo;
|
||||||
using Il2CppSystemType = Il2CppSystem.Type;
|
using Il2CppSystemType = Il2CppSystem.Type;
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
public static class ReflectionExtensions
|
public static class ReflectionExtensions
|
||||||
{
|
{
|
||||||
@@ -53,4 +55,14 @@ public static class ReflectionExtensions
|
|||||||
{
|
{
|
||||||
return AccessTools.Method(AccessTools.Method(type, methodName).ToIl2CppMethodInfo().GetEnumeratorMoveNextType().ToSystemType(), "MoveNext");
|
return AccessTools.Method(AccessTools.Method(type, methodName).ToIl2CppMethodInfo().GetEnumeratorMoveNextType().ToSystemType(), "MoveNext");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<MethodBase> GetMethods(this Type type, BindingFlags bindingAttr, Type returnType, params Type[] parameterTypes)
|
||||||
|
{
|
||||||
|
return type.GetMethods(bindingAttr).Where(x => x.ReturnType == returnType && x.GetParameters().Select(x => x.ParameterType).SequenceEqual(parameterTypes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<MethodBase> GetMethods(this Type type, Type returnType, params Type[] parameterTypes)
|
||||||
|
{
|
||||||
|
return type.GetMethods(AccessTools.all, returnType, parameterTypes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Il2CppInterop.Runtime.Attributes;
|
||||||
|
using Il2CppInterop.Runtime.Injection;
|
||||||
|
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||||
|
using Reactor.Utilities.Attributes;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
|
public static class StreamExtensions
|
||||||
|
{
|
||||||
|
[RegisterInIl2Cpp]
|
||||||
|
public class StreamWrapper : Il2CppSystem.IO.Stream
|
||||||
|
{
|
||||||
|
private readonly Stream _stream;
|
||||||
|
|
||||||
|
#pragma warning disable 8618
|
||||||
|
public StreamWrapper(IntPtr ptr) : base(ptr) { }
|
||||||
|
#pragma warning restore 8618
|
||||||
|
|
||||||
|
public StreamWrapper(Stream stream) : base(ClassInjector.DerivedConstructorPointer<StreamWrapper>())
|
||||||
|
{
|
||||||
|
ClassInjector.DerivedConstructorBody(this);
|
||||||
|
_stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HideFromIl2Cpp]
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe Span<byte> GetSpan(Il2CppStructArray<byte> buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
var rawBuffer = (byte*) buffer.Pointer + 4 * IntPtr.Size;
|
||||||
|
return new Span<byte>(rawBuffer + offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Read(Il2CppStructArray<byte> buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
return _stream.Read(GetSpan(buffer, offset, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Il2CppStructArray<byte> buffer, int offset, int count)
|
||||||
|
{
|
||||||
|
_stream.Write(GetSpan(buffer, offset, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Flush()
|
||||||
|
{
|
||||||
|
_stream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
_stream.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
_stream.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long Seek(long offset, Il2CppSystem.IO.SeekOrigin origin)
|
||||||
|
{
|
||||||
|
return _stream.Seek(offset, origin switch
|
||||||
|
{
|
||||||
|
Il2CppSystem.IO.SeekOrigin.Begin => SeekOrigin.Begin,
|
||||||
|
Il2CppSystem.IO.SeekOrigin.Current => SeekOrigin.Current,
|
||||||
|
Il2CppSystem.IO.SeekOrigin.End => SeekOrigin.End,
|
||||||
|
_ => throw new ArgumentOutOfRangeException(nameof(origin), origin, null),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetLength(long value)
|
||||||
|
{
|
||||||
|
_stream.SetLength(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanRead => _stream.CanRead;
|
||||||
|
public override bool CanSeek => _stream.CanSeek;
|
||||||
|
public override bool CanWrite => _stream.CanWrite;
|
||||||
|
public override long Length => _stream.Length;
|
||||||
|
|
||||||
|
public override long Position
|
||||||
|
{
|
||||||
|
get => _stream.Position;
|
||||||
|
set => _stream.Position = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps a System Stream into an Il2Cpp Stream
|
||||||
|
/// </summary>
|
||||||
|
public static StreamWrapper AsIl2Cpp(this Stream stream) => new(stream);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fully read <paramref name="input"/> stream, can be used as workaround for il2cpp streams.
|
||||||
|
/// </summary>
|
||||||
|
public static byte[] ReadFully(this Stream input)
|
||||||
|
{
|
||||||
|
using var ms = new MemoryStream();
|
||||||
|
input.CopyTo(ms);
|
||||||
|
return ms.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
|
public static class UnityExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the color as a hexadecimal string in the format "RRGGBBAA".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="color">The color to be converted.</param>
|
||||||
|
/// <returns>Hexadecimal string representing the color.</returns>
|
||||||
|
/// <remarks>https://docs.unity3d.com/ScriptReference/ColorUtility.ToHtmlStringRGBA.html</remarks>
|
||||||
|
public static string ToHtmlStringRGBA(this Color32 color)
|
||||||
|
{
|
||||||
|
return $"{color.r:X2}{color.g:X2}{color.b:X2}{color.a:X2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="ToHtmlStringRGBA(UnityEngine.Color32)"/>
|
||||||
|
public static string ToHtmlStringRGBA(this Color color)
|
||||||
|
{
|
||||||
|
return ((Color32) color).ToHtmlStringRGBA();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly int _outline = Shader.PropertyToID("_Outline");
|
||||||
|
private static readonly int _outlineColor = Shader.PropertyToID("_OutlineColor");
|
||||||
|
private static readonly int _addColor = Shader.PropertyToID("_AddColor");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets color outline for renderers using default Among Us shader
|
||||||
|
/// </summary>
|
||||||
|
public static void SetOutline(this Renderer renderer, Color? color)
|
||||||
|
{
|
||||||
|
renderer.material.SetFloat(_outline, color.HasValue ? 1 : 0);
|
||||||
|
|
||||||
|
if (color.HasValue)
|
||||||
|
{
|
||||||
|
renderer.material.SetColor(_outlineColor, color.Value);
|
||||||
|
renderer.material.SetColor(_addColor, color.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Reactor.Extensions;
|
namespace Reactor.Utilities.Extensions;
|
||||||
|
|
||||||
public static class UnityObjectExtensions
|
public static class UnityObjectExtensions
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Il2CppSystem.Runtime.CompilerServices;
|
using Il2CppSystem.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
public sealed class Il2CppEqualityComparer<T> : IEqualityComparer<T> where T : Il2CppSystem.Object
|
public sealed class Il2CppEqualityComparer<T> : IEqualityComparer<T> where T : Il2CppSystem.Object
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using Reactor.Utilities.Extensions;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.ImGui;
|
||||||
|
|
||||||
|
public class DragWindow : Window
|
||||||
|
{
|
||||||
|
public DragWindow(Rect rect, string title, Action<int> func) : base(rect, title, func)
|
||||||
|
{
|
||||||
|
Func = id =>
|
||||||
|
{
|
||||||
|
func(id);
|
||||||
|
|
||||||
|
UnityEngine.GUI.DragWindow(new Rect(0, 0, 10000, 20));
|
||||||
|
Rect = Rect.ClampScreen();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public DragWindow(Rect rect, string title, Action func) : this(rect, title, id => func())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using Reactor.Utilities.Extensions;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities.ImGui;
|
||||||
|
|
||||||
|
public class Window
|
||||||
|
{
|
||||||
|
private static int _lastWindowId;
|
||||||
|
|
||||||
|
public static int NextWindowId()
|
||||||
|
{
|
||||||
|
return _lastWindowId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Id { get; set; } = NextWindowId();
|
||||||
|
|
||||||
|
public bool Enabled { get; set; } = true;
|
||||||
|
public Rect Rect { get; set; }
|
||||||
|
public Action<int> Func { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public Window(Rect rect, string title, Action<int> func)
|
||||||
|
{
|
||||||
|
Rect = rect;
|
||||||
|
Title = title;
|
||||||
|
Func = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Window(Rect rect, string title, Action func) : this(rect, title, id => func())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGUI()
|
||||||
|
{
|
||||||
|
if (Enabled)
|
||||||
|
{
|
||||||
|
if (Event.current.type == EventType.Layout)
|
||||||
|
{
|
||||||
|
Rect = Rect.ResetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect = GUILayout.Window(Id, Rect, Func, Title);
|
||||||
|
|
||||||
|
if ((Input.GetMouseButtonDown(0) || Input.GetMouseButtonDown(1)) && Rect.Contains(new Vector2(Input.mousePosition.x, Screen.height - Input.mousePosition.y)))
|
||||||
|
{
|
||||||
|
Input.ResetInputAxes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using BepInEx.Core.Logging.Interpolation;
|
using BepInEx.Core.Logging.Interpolation;
|
||||||
using BepInEx.Unity.IL2CPP;
|
|
||||||
using BepInEx.Logging;
|
using BepInEx.Logging;
|
||||||
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
public static class Logger<T> where T : BasePlugin
|
public static class Logger<T> where T : BasePlugin
|
||||||
{
|
{
|
||||||
@@ -3,7 +3,7 @@ using System.Linq;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using BepInEx.Unity.IL2CPP;
|
using BepInEx.Unity.IL2CPP;
|
||||||
|
|
||||||
namespace Reactor;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
public static class PluginSingleton<T> where T : BasePlugin
|
public static class PluginSingleton<T> where T : BasePlugin
|
||||||
{
|
{
|
||||||
@@ -2,11 +2,10 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using Reactor.Extensions;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Object = UnityEngine.Object;
|
using Object = UnityEngine.Object;
|
||||||
|
|
||||||
namespace Reactor.Patches;
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
internal class RegionInfoWatcher : IDisposable
|
internal class RegionInfoWatcher : IDisposable
|
||||||
{
|
{
|
||||||
@@ -57,14 +56,16 @@ internal class RegionInfoWatcher : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
private static class WritePatch
|
internal static class WriteAllTextPatch
|
||||||
{
|
{
|
||||||
|
[HarmonyTargetMethod]
|
||||||
public static MethodBase TargetMethod()
|
public static MethodBase TargetMethod()
|
||||||
{
|
{
|
||||||
var type = Type.GetType("FileIO, Assembly-CSharp", false) ?? Type.GetType("Innersloth.IO.FileIO, Assembly-CSharp", true);
|
var type = Type.GetType("FileIO, Assembly-CSharp", false) ?? Type.GetType("Innersloth.IO.FileIO, Assembly-CSharp", true);
|
||||||
return AccessTools.Method(type, "WriteAllText");
|
return AccessTools.Method(type, "WriteAllText");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPrefix]
|
||||||
public static bool Prefix(string path, string contents)
|
public static bool Prefix(string path, string contents)
|
||||||
{
|
{
|
||||||
// Among Us' region loading code unfortunately contains a call
|
// Among Us' region loading code unfortunately contains a call
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine.Events;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
|
namespace Reactor.Utilities;
|
||||||
|
|
||||||
|
public static class SceneManagerUtilities
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a delegate to get one notification when a scene has loaded.
|
||||||
|
/// </summary>
|
||||||
|
public static void once_sceneLoaded(Action<Scene, LoadSceneMode> value)
|
||||||
|
{
|
||||||
|
UnityAction<Scene, LoadSceneMode>? unityAction = null;
|
||||||
|
|
||||||
|
unityAction = (Action<Scene, LoadSceneMode>) ((scene, loadMode) =>
|
||||||
|
{
|
||||||
|
SceneManager.remove_sceneLoaded(unityAction);
|
||||||
|
value.Invoke(scene, loadMode);
|
||||||
|
});
|
||||||
|
|
||||||
|
SceneManager.add_sceneLoaded(unityAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user