1 Commits
Author SHA1 Message Date
js6pak 1a7755b987 Localize Reactor with fluent 2022-10-26 13:08:44 +02:00
92 changed files with 1632 additions and 2703 deletions

No files matched your search

+11 -11
View File
@@ -4,14 +4,14 @@ on: ["push", "pull_request"]
jobs:
build:
runs-on: ubuntu-24.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
submodules: true
- uses: actions/cache@v4
- uses: actions/cache@v3
with:
path: |
~/.nuget/packages
@@ -21,36 +21,36 @@ jobs:
${{ runner.os }}-nuget-
- name: Setup .NET
uses: actions/setup-dotnet@v4
uses: actions/setup-dotnet@v2
with:
dotnet-version: 8.0.x
dotnet-version: 6.x
- name: Run the Cake script
uses: cake-build/cake-action@v3
uses: cake-build/cake-action@v1
with:
verbosity: Diagnostic
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: Reactor.dll
path: Reactor/bin/Release/net6.0/Reactor.dll
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: Reactor.nupkg
path: Reactor/bin/Release/Reactor.*.nupkg
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: Reactor.Networking.Shared.nupkg
path: Reactor.Networking.Shared/bin/Release/*.nupkg
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: Reactor.Debugger.dll
path: Reactor.Debugger/bin/Release/net6.0/Reactor.Debugger.dll
- uses: softprops/action-gh-release@v2
- uses: softprops/action-gh-release@v1
if: github.ref_type == 'tag'
with:
draft: true
+9 -10
View File
@@ -9,15 +9,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: actions/cache@v4
- uses: actions/cache@v3
with:
path: |
~/Unity/Hub/Editor
~/.config/unityhub
~/.local/share/unity3d/Unity/Unity_lic.ulf
key: unity-${{ hashFiles('./Reactor.Assets/ProjectSettings/ProjectVersion.txt') }}
key: unity-2020.3.22f1
- name: Setup Unity
uses: js6pak/setup-unity@master
@@ -26,17 +25,17 @@ jobs:
unity-modules: windows-mono android
- name: Activate Unity
env:
UNITY_USERNAME: ${{ secrets.UNITY_USERNAME }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
run: |
/opt/unityhub/UnityLicensingClient_V1/Unity.Licensing.Client --activate-ulf --username "$UNITY_USERNAME" --password "$UNITY_PASSWORD"
uses: js6pak/activate-unity@master
with:
unity-username: ${{ secrets.UNITY_USERNAME }}
unity-password: ${{ secrets.UNITY_PASSWORD }}
unity-authenticator-key: ${{ secrets.UNITY_AUTHENTICATOR_KEY }}
- name: Build
working-directory: ./Reactor.Assets
run: bash ./build.sh
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: bundles
path: ./Reactor/Assets/*.bundle
+3 -3
View File
@@ -1,10 +1,10 @@
<Project>
<ItemGroup>
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.4.15" PrivateAssets="all" />
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.662" Private="false" ExcludeAssets="runtime;native" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2022.10.25" PrivateAssets="all" />
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1" PrivateAssets="all" ExcludeAssets="runtime" />
</ItemGroup>
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
+2 -7
View File
@@ -8,7 +8,7 @@
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<VersionPrefix>2.5.0</VersionPrefix>
<VersionPrefix>2.0.0</VersionPrefix>
<VersionSuffix>dev</VersionSuffix>
<Authors>NuclearPowered</Authors>
@@ -16,11 +16,6 @@
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/NuclearPowered/Reactor</RepositoryUrl>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
<!-- SourceLink -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>
<ItemGroup>
@@ -35,7 +30,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" />
</ItemGroup>
<PropertyGroup>
+4 -4
View File
@@ -69,14 +69,14 @@ internal static class Build
}
}
private static string GetTargetName(BuildTarget target, bool includeArchitecture = false)
private static string GetTargetName(BuildTarget target)
{
return target switch
{
BuildTarget.StandaloneWindows => includeArchitecture ? "win-x86" : "win",
BuildTarget.StandaloneWindows64 => includeArchitecture ? "win-x64" : "win",
BuildTarget.StandaloneWindows => "win-x86",
BuildTarget.StandaloneWindows64 => "win-x64",
BuildTarget.Android => "android",
BuildTarget.StandaloneLinux64 => includeArchitecture ? "linux-x64" : "linux",
BuildTarget.StandaloneLinux64 => "linux-x64",
_ => throw new ArgumentOutOfRangeException(nameof(target), target, null),
};
}
+3 -3
View File
@@ -1,10 +1,10 @@
{
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.ide.rider": "3.0.31",
"com.unity.ide.visualstudio": "2.0.22",
"com.unity.ide.rider": "2.0.7",
"com.unity.ide.visualstudio": "2.0.16",
"com.unity.ide.vscode": "1.2.5",
"com.unity.toolchain.linux-x86_64": "2.0.9",
"com.unity.toolchain.linux-x86_64": "2.0.2",
"com.unity.modules.ai": "1.0.0",
"com.unity.modules.androidjni": "1.0.0",
"com.unity.modules.animation": "1.0.0",
+11 -11
View File
@@ -8,22 +8,22 @@
},
"com.unity.ext.nunit": {
"version": "1.0.6",
"depth": 1,
"depth": 2,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "3.0.31",
"version": "2.0.7",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.ext.nunit": "1.0.6"
"com.unity.test-framework": "1.1.1"
},
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.22",
"version": "2.0.16",
"depth": 0,
"source": "registry",
"dependencies": {
@@ -39,23 +39,23 @@
"url": "https://packages.unity.com"
},
"com.unity.sysroot": {
"version": "2.0.10",
"version": "2.0.3",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.sysroot.linux-x86_64": {
"version": "2.0.9",
"version": "2.0.2",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.sysroot": "2.0.10"
"com.unity.sysroot": "2.0.3"
},
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.1.33",
"version": "1.1.29",
"depth": 1,
"source": "registry",
"dependencies": {
@@ -66,12 +66,12 @@
"url": "https://packages.unity.com"
},
"com.unity.toolchain.linux-x86_64": {
"version": "2.0.9",
"version": "2.0.2",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.sysroot": "2.0.10",
"com.unity.sysroot.linux-x86_64": "2.0.9"
"com.unity.sysroot": "2.0.3",
"com.unity.sysroot.linux-x86_64": "2.0.2"
},
"url": "https://packages.unity.com"
},
@@ -1,2 +1,2 @@
m_EditorVersion: 2020.3.45f1
m_EditorVersionWithRevision: 2020.3.45f1 (660cd1701bd5)
m_EditorVersion: 2020.3.22f1
m_EditorVersionWithRevision: 2020.3.22f1 (e1a7f79fd887)
+3 -3
View File
@@ -1,12 +1,12 @@
#!/bin/bash
UNITY_VERSION=2020.3.45f1
UNITY_VERSION=2020.3.22f1
if [[ ! -v UNITY_PATH ]]; then
if command -v unityhub &>/dev/null; then
echo "Trying to get unity path from unityhub..."
UNITYHUB_INSTALL_PATH=$(unityhub -- --headless install-path)
UNITYHUB_INSTALL_PATH=$(unityhub --headless install-path)
UNITY_PATH="$UNITYHUB_INSTALL_PATH/$UNITY_VERSION/Editor/Unity"
if [[ ! -f $UNITY_PATH ]]; then
@@ -22,4 +22,4 @@ fi
echo "UNITY_PATH = $UNITY_PATH"
rm Library -rf # TODO figure out why having Library cached makes invalid bundles in batchmode
"$UNITY_PATH" -batchmode -nographics -quit -logFile "-" -projectPath "$PWD" -executeMethod Build.BuildAssetBundles
$UNITY_PATH -batchmode -nographics -quit -logFile "-" -projectPath $pwd -executeMethod Build.BuildAssetBundles
+3 -3
View File
@@ -16,7 +16,7 @@ namespace Reactor.Benchmarks;
[StopOnFirstError, Config(typeof(Config))]
public class AssetBundleBenchmarks
{
private sealed class Config : ManualConfig
private class Config : ManualConfig
{
public Config()
{
@@ -29,7 +29,7 @@ public class AssetBundleBenchmarks
public static IEnumerable<string> ValuesForAssetBundleName()
{
yield return $"{AssetBundleManager.GetFileName("default", false)}";
yield return $"default-{AssetBundleManager.TargetName}{AssetBundleManager.BundleExtension}";
// yield return "submerged";
}
@@ -41,7 +41,7 @@ public class AssetBundleBenchmarks
private AssetBundle LoadAll(AssetBundle assetBundle)
{
ArgumentNullException.ThrowIfNull(assetBundle);
if (assetBundle == null) throw new ArgumentNullException(nameof(assetBundle));
assetBundle.LoadAllAssets();
return assetBundle;
+1 -1
View File
@@ -8,7 +8,7 @@
<ItemGroup>
<ProjectReference Include="..\Reactor\Reactor.csproj" Private="false" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.10" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.2" />
</ItemGroup>
<Import Project="../AmongUs.props" />
+154 -195
View File
@@ -4,26 +4,28 @@
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2025.4.15, )",
"resolved": "2025.4.15",
"contentHash": "R3RxzHGZOGUJ9nMwrP0cjS6g+sh60QUU506Mo47lh17155enUjH6PtErijihSoU7t3aQpzCIyC67W3XrrHhH4g=="
"requested": "[2022.10.25, )",
"resolved": "2022.10.25",
"contentHash": "PWgkH/VvMlShVhZB8G432q0tnMaNVZrbIdbEMCZN/fETUlT/ch+qQj4PdTcZhPHREbnJHH3ijHxlca1d7QMBcQ=="
},
"BenchmarkDotNet": {
"type": "Direct",
"requested": "[0.13.10, )",
"resolved": "0.13.10",
"contentHash": "p/LrTtR5TlwhZIvy2hG9VzTFWEDPS90r3QP9Q9pL4/B1iXzC/JNrpYyCWW3Xeg4vuiq/qV8hvJkJmT1sj+5LSw==",
"requested": "[0.13.2, )",
"resolved": "0.13.2",
"contentHash": "82IflYxY8qnQXEA3kXtqC9pntrkJYJZbQ9PV7hEV/XcfCtOdwLz84ilyO8tLRVbiliWttvmt/v44P+visN+fPQ==",
"dependencies": {
"BenchmarkDotNet.Annotations": "0.13.10",
"CommandLineParser": "2.9.1",
"Gee.External.Capstone": "2.3.0",
"BenchmarkDotNet.Annotations": "0.13.2",
"CommandLineParser": "2.4.3",
"Iced": "1.17.0",
"Microsoft.CodeAnalysis.CSharp": "4.1.0",
"Microsoft.CodeAnalysis.CSharp": "3.0.0",
"Microsoft.Diagnostics.Runtime": "2.2.332302",
"Microsoft.Diagnostics.Tracing.TraceEvent": "3.0.2",
"Microsoft.DotNet.PlatformAbstractions": "3.1.6",
"Perfolizer": "[0.2.1]",
"System.Management": "5.0.0"
"Perfolizer": "0.2.1",
"System.Management": "6.0.0",
"System.Reflection.Emit": "4.7.0",
"System.Reflection.Emit.Lightweight": "4.7.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"BepInEx.AutoPlugin": {
@@ -34,126 +36,74 @@
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.1.0-rc.1, )",
"resolved": "2.1.0-rc.1",
"contentHash": "WI/7TbJwWl5P4B6UXGtKI1VMe6fA6h3fcbp3ZjJKqOBQ5MJfDMmeVB4fb+RW1tUQdxnlSWV3Ul62PHFyTqp4PA=="
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.735, )",
"resolved": "6.0.0-be.735",
"contentHash": "2+eFJGKMR1GFPeU9wuF+TVrMANIaWIc/6N9e8x4b7b/fNiY9B6vicYNiMDb2deYQpWZtOei+2btnar5dDE5BPg==",
"requested": "[6.0.0-be.662, )",
"resolved": "6.0.0-be.662",
"contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.735",
"BepInEx.Unity.Common": "6.0.0-be.735",
"HarmonyX": "2.10.2",
"Iced": "1.21.0",
"Il2CppInterop.Generator": "1.4.6-ci.426",
"Il2CppInterop.HarmonySupport": "1.4.6-ci.426",
"Il2CppInterop.Runtime": "1.4.6-ci.426",
"MonoMod.RuntimeDetour": "22.7.31.1",
"Samboy063.Cpp2IL.Core": "2022.1.0-pre-release.19"
"BepInEx.Core": "6.0.0-be.662",
"BepInEx.Unity.Common": "6.0.0-be.662",
"HarmonyX": "2.10.0",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.3.0",
"Il2CppInterop.HarmonySupport": "1.3.0",
"Il2CppInterop.Runtime": "1.3.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.556, )",
"resolved": "1.2.0-beta.556",
"contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.556"
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AsmResolver": {
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "M5btCR/rmrx32jZsoN6CLQ/VQk8lN8hvPb6lgojua7pjNoo7StAl92koMC8qz4vzZyH2CNqxLSDoswRvyyK/vA=="
},
"AsmResolver.DotNet": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "PTq8nNQvhgTxF1iARCknffCsu7Iq9B0kN7TVC8iMaU7uEYog3xvVqH/0+TreY8GW74/+MqhZt/yEFsvS4oAduQ==",
"dependencies": {
"AsmResolver.PE": "6.0.0-beta.1"
}
},
"AsmResolver.PE": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "KadLvx/zzFCJyF+E4jG6jPE1d0iJquzL6+hm8GBivBAs6nwHC8s6g4c857QwQCzXMWza6Vz5Q+3hFiNuOfKaWQ==",
"dependencies": {
"AsmResolver.PE.File": "6.0.0-beta.1"
}
},
"AsmResolver.PE.File": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "+lusB9UMHevI5aQsu73NQ1ctPMLFvyHAsEf8vjaJ/py+kX1DkU0JkbERtBRmaf58/hBZ7cyrE7gFnjoo7Bbg7A==",
"dependencies": {
"AsmResolver": "6.0.0-beta.1"
}
},
"AssetRipper.CIL": {
"type": "Transitive",
"resolved": "1.1.2",
"contentHash": "BRPcHORadIzSFkrVOvGkSs54j19mQdXH8dmRTVM51mS8MZLSbTpi9CDPpnWN2IdDsILUrAqbPUFo3zJodYxErw==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1"
}
},
"AssetRipper.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "wOr5PQPL/2ZfD7+ebt6cpRbUhSzSY5nlHGHjjzuQRiU5zkQlqQNwWDLX0M3smrm5IkaDvONkmDjFMKTlZJmyuQ=="
},
"AssetRipper.Primitives": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "djZbN/+EXmI+Oia9Pm0LyjZVCPLf60TPSL5rGb7mBEYM5F4CN3nPFXvl2yA5LanPZoHS1Yq7PghGUmkP7Pv9RQ=="
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BenchmarkDotNet.Annotations": {
"type": "Transitive",
"resolved": "0.13.10",
"contentHash": "abYKp+P5NBuam7q0w7AFgOYF3nqAvKBw6MLq96Kjk1WdaRDNpgBc6uCgOP4pVIH/g0IF9d4ubnFLBwiJuIAHMw=="
"resolved": "0.13.2",
"contentHash": "+SGOYyXT6fiagbtrni38B8BqBgjruYKU3PfROI0lDIYo8jQ+APUmLKMEswK7zwR5fEOCrDmoAHSH6oykBkqPgA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "FuHm9UCzjSKeiZJc3IF70Fiuqi+FynRn62PwBoOeZcHK3/qm+vl1YwbZyFlmUyf45g+UKxg2Td40iZGx88LVAQ==",
"resolved": "6.0.0-be.662",
"contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==",
"dependencies": {
"HarmonyX": "2.10.2",
"MonoMod.Utils": "22.7.31.1",
"HarmonyX": "2.10.0",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "vmK//OBSr+jotqTk//HSdvHtMFTKu+NlQkiEsvr0dZApTVmQM2AgpVMhEAakQPmrSsM6LRJIHCBcLFO1ypfMPQ==",
"resolved": "6.0.0-be.662",
"contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"MonoMod.Utils": "22.7.31.1"
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"CommandLineParser": {
"type": "Transitive",
"resolved": "2.9.1",
"contentHash": "OE0sl1/sQ37bjVsPKKtwQlWDgqaxWgtme3xZz7JssWUzg5JpMIyHgCTY9MVMxOg48fJ1AgGT3tgdH5m/kQ5xhA=="
},
"Disarm": {
"type": "Transitive",
"resolved": "2022.1.0-master.57",
"contentHash": "/dkg7hg8iPBQN4bTV1lMQacarH6fMpgUXhJuo6iI7Wv7YpH7g5F9hJfje7dSMhqG0YlDacLuyWvcph5GzKUXog=="
},
"Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.0",
"contentHash": "2ap/rYmjtzCOT8hxrnEW/QeiOt+paD8iRrIcdKX0cxVwWLFa1e+JDBNeECakmccXrSFeBQuu5AV8SNkipFMMMw=="
"resolved": "2.4.3",
"contentHash": "U2FC9Y8NyIxxU6MpFFdWWu1xwiqz/61v/Doou7kmVjpeIEMLWyiNNkzNlSE84kyJ0O1LKApuEj5z48Ow0Hi4OQ=="
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.2",
"contentHash": "/5WwkxXX8mPsRuigQt957rJGx1f0dDQxk+bvk4yYITKFjXas9Em+O71zEP8X0ym8OFQQ2XH/2SxS4NC7vEC+Xg==",
"resolved": "2.10.0",
"contentHash": "4ayiy/dlCiW86K2N7Jvbf+VpI5wvP7dncv/6oRmfwRi32UCmCRzCGzsxdMfzJZkp6/26oBW+DrD8vi4UejzVAg==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
@@ -161,13 +111,13 @@
},
"Iced": {
"type": "Transitive",
"resolved": "1.21.0",
"contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "pI0kU0qqJKMP6z9eFz4+WJtGIwklfPxW2yWEY9vKnrN9bbYMusK3v5uFWV8al7S/HPSATV5jNWH1hyTvP7kglA==",
"resolved": "1.3.0",
"contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
@@ -176,29 +126,61 @@
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "kecdx/vbNl0RtfzfYW592jU8PMyq1JbzpvoJSvqwO+tV6icp9SljXy6yG8bT/wt0gaPj9mFUNDTe2Wu6M6XGZQ==",
"resolved": "1.3.0",
"contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==",
"dependencies": {
"Il2CppInterop.Common": "1.4.6-ci.426",
"Il2CppInterop.Common": "1.3.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "rd2T5o6SybIc12hmX3HktTF5n27hFb0w4mNSExq7h1YsmrNlt7x+Ac1MBnnB0JwPLIg7w8LjnKjoIX6Gf626ng==",
"resolved": "1.3.0",
"contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.6-ci.426"
"Il2CppInterop.Runtime": "1.3.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "0O0oI7gOqJixrsjvh1firhuGYK3Yr0uDLp6Q+t5CfcTMmeEX8Plk3pqAP9ZYyilBvh7uW0gv4Golqz08L1GXug==",
"resolved": "1.3.0",
"contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.6-ci.426"
"Il2CppInterop.Common": "1.3.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Linguini.Bundle": {
"type": "Transitive",
"resolved": "0.3.1",
"contentHash": "k3D0IBSsS91T0G9rYACRYtAS27NDTGz4T3ygHhbhaFdA9i3cCfCpR39MqYEpoA1Ark3lzmvklHePmRCX5EQi1A==",
"dependencies": {
"Linguini.Shared": "0.3.0",
"Linguini.Syntax": "0.3.0"
}
},
"Linguini.Shared": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "rEYA9jWU1Nc9iDuPKar+4IVXjFbGrcNyYZCeU6hiWQoS4nA2UecHu36Rp4bxzasvRGda4FB2JZqty75m4e26VQ=="
},
"Linguini.Syntax": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "v8YV3xPFZfP+OSWjMd6yysp+o7cNnQXxq/slN8Yekoi+dFjsTNF0YiQWJIwg1j2FUbs6claJxY9R1FFlc4s6MA==",
"dependencies": {
"Linguini.Shared": "0.3.0"
}
},
"Microsoft.Bcl.AsyncInterfaces": {
@@ -208,29 +190,29 @@
},
"Microsoft.CodeAnalysis.Analyzers": {
"type": "Transitive",
"resolved": "3.3.3",
"contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ=="
"resolved": "2.6.2-beta2",
"contentHash": "rg5Ql73AmGCMG5Q40Kzbndq7C7S4XvsJA+2QXfZBCy2dRqD+a7BSbx/3942EoRUJ/8Wh9+kLg2G2qC46o3f1Aw=="
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "4.1.0",
"contentHash": "bNzTyxP3iD5FPFHfVDl15Y6/wSoI7e3MeV0lOaj9igbIKTjgrmuw6LoVJ06jUNFA7+KaDC/OIsStWl/FQJz6sQ==",
"resolved": "3.0.0",
"contentHash": "HEnLZ9Op5IoXeuokhfSLIXstXfEyPzXhQ/xsnvUmxzb+7YpwuLk57txArzGs/Wne5bWmU7Uey4Q1jUZ3++heqg==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.3",
"System.Collections.Immutable": "5.0.0",
"System.Memory": "4.5.4",
"System.Reflection.Metadata": "5.0.0",
"System.Runtime.CompilerServices.Unsafe": "5.0.0",
"System.Text.Encoding.CodePages": "4.5.1",
"System.Threading.Tasks.Extensions": "4.5.4"
"Microsoft.CodeAnalysis.Analyzers": "2.6.2-beta2",
"System.Collections.Immutable": "1.5.0",
"System.Memory": "4.5.1",
"System.Reflection.Metadata": "1.6.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.0",
"System.Text.Encoding.CodePages": "4.5.0",
"System.Threading.Tasks.Extensions": "4.5.0"
}
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Transitive",
"resolved": "4.1.0",
"contentHash": "sbu6kDGzo9bfQxuqWpeEE7I9P30bSuZEnpDz9/qz20OU6pm79Z63+/BsAzO2e/R/Q97kBrpj647wokZnEVr97w==",
"resolved": "3.0.0",
"contentHash": "hWFUxc0iUbVvIKWJODErOeOa5GiqZuEcetxaCfHqZ04zHy0ZCLx3v4/TdF/6Erx1mXPHfoT2Tiz5rZCQZ6OyxQ==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "[4.1.0]"
"Microsoft.CodeAnalysis.Common": "[3.0.0]"
}
},
"Microsoft.Diagnostics.NETCore.Client": {
@@ -330,23 +312,14 @@
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ=="
"resolved": "2.0.0",
"contentHash": "VdLJOCXhZaEMY7Hm2GKiULmn7IEPFE4XC5LPSfBVCUIA8YLZVh846gtfBJalsPQF2PlzdD7ecX7DZEulJ402ZQ=="
},
"Microsoft.NETCore.Targets": {
"type": "Transitive",
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Microsoft.Win32.Registry": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
"dependencies": {
"System.Security.AccessControl": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"Mono.Cecil": {
"type": "Transitive",
"resolved": "0.11.4",
@@ -354,11 +327,11 @@
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nxVJTvQbWAujaogt5XX3eAy7d22t66Z88aWg9sirPLO9rR/6yNCHAyZpgxXrOsIobZVW0IEZPqNMOBhgke25/w==",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.7.31.1",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
@@ -369,8 +342,8 @@
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nI0E1oadXS1iMbfwfCzYF08C1jRQR9cnnHv66a4BSPd4sGu2p6g4BmctCWsdAB6oGKkSJUhcfHfxcfTsDyB94Q==",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
@@ -489,51 +462,47 @@
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "mAYIrMo0VdOZzh1NS5bZeflg80gtYNY7kZo9q/blEYheUPyLXu5ozQOjX+Bq2yDh40pA+yiE2MXTnN2Is2hjgw==",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1",
"AssetRipper.CIL": "1.1.2",
"AssetRipper.Gee.External.Capstone": "2.3.2",
"Disarm": "2022.1.0-master.57",
"Iced": "1.21.0",
"Samboy063.LibCpp2IL": "2022.1.0-pre-release.19",
"StableNameDotNet": "0.1.0-pre-release.19"
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "/n8p81ltd38BeNNS2xUNPGMSzxk/UGXr9cRNqG1MaLogzANNNrvCAXqWmNMM3tZctjp7vqTxEA+e4J4ngul8Fg==",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"Samboy063.WasmDisassembler": "2022.1.0-pre-release.19"
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "uVQdYm/J6+jJ1xt6GJ3hNhXhciwlX+LmHTPITu9jjZ75T33YJuuTD7pLVYuMymr+4gSVisg7f1wterFSyqJBWA=="
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StableNameDotNet": {
"type": "Transitive",
"resolved": "0.1.0-pre-release.19",
"contentHash": "5BPWtntv3PXeFIg9CuGW6OM3f5GnwvdQJbzRpufPsistFwFyt1xYW1wSDr+QIdDO7vLndr7iNpWD3FyYp9LL4g=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.556",
"contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ=="
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.CodeDom": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "JPJArwA1kdj8qDAkY2XGjSWoYnqiM7q/3yRNkt6n28Mnn95MuEGkZXUbPBf7qc3IjwrGY5ttQon7yqHZyQJmOQ=="
"resolved": "6.0.0",
"contentHash": "CPc6tWO1LAer3IzfZufDBRL+UZQcj5uS207NHALQzP84Vp/z6wF0Aa0YZImOQY8iStY0A2zI/e3ihKNPfUm8XA=="
},
"System.Collections": {
"type": "Transitive",
@@ -749,18 +718,16 @@
},
"System.Management": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "MF1CHaRcC+MLFdnDthv4/bKWBZnlnSpkGqa87pKukQefgEdwtb9zFW6zs0GjPp73qtpYYg4q6PEKbzJbxCpKfw==",
"resolved": "6.0.0",
"contentHash": "sHsESYMmPDhQuOC66h6AEOs/XowzKsbT9srMbX71TCXP58hkpn1BqBjdmKj1+DCA/WlBETX1K5WjQHwmV0Txrg==",
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"Microsoft.Win32.Registry": "5.0.0",
"System.CodeDom": "5.0.0"
"System.CodeDom": "6.0.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
"resolved": "4.5.3",
"contentHash": "3oDzvc/zzetpTKWMShs1AADwZjQ/36HnsufHRPcOjyRAAMLDlu2iD33MBI2opxnezcVUtXyqDXXjoFMOU9c7SA=="
},
"System.Net.Http": {
"type": "Transitive",
@@ -846,8 +813,8 @@
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
"resolved": "1.6.0",
"contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ=="
},
"System.Reflection.Primitives": {
"type": "Transitive",
@@ -934,15 +901,6 @@
"System.Runtime.Extensions": "4.3.0"
}
},
"System.Security.AccessControl": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
"dependencies": {
"Microsoft.NETCore.Platforms": "5.0.0",
"System.Security.Principal.Windows": "5.0.0"
}
},
"System.Security.Cryptography.Algorithms": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1087,11 +1045,6 @@
"runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0"
}
},
"System.Security.Principal.Windows": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
},
"System.Text.Encoding": {
"type": "Transitive",
"resolved": "4.3.0",
@@ -1104,11 +1057,11 @@
},
"System.Text.Encoding.CodePages": {
"type": "Transitive",
"resolved": "4.5.1",
"contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==",
"resolved": "4.5.0",
"contentHash": "S0wEUiKcLvRlkFUXca8uio1UQ5bYQzYgOmOKtCqaBQC3GR9AJjh43otcM32IGsAyvadFTaAMw9Irm6dS4Evfng==",
"dependencies": {
"Microsoft.NETCore.Platforms": "2.1.2",
"System.Runtime.CompilerServices.Unsafe": "4.5.2"
"Microsoft.NETCore.Platforms": "2.0.0",
"System.Runtime.CompilerServices.Unsafe": "4.5.0"
}
},
"System.Threading": {
@@ -1135,10 +1088,16 @@
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"reactor": {
"type": "Project",
"dependencies": {
"BepInEx.Unity.IL2CPP": "[6.0.0-be.735, )"
"BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )",
"Linguini.Bundle": "[0.3.1, )"
}
}
}
@@ -1,82 +0,0 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Pipes;
using InnerNet;
using Reactor.Debugger.AutoJoin.Messages;
using Reactor.Utilities;
namespace Reactor.Debugger.AutoJoin;
internal sealed class AutoJoinClientConnection : AutoJoinConnection
{
public const string PipeName = "Reactor.Debugger.AutoJoin";
private AutoJoinClientConnection(NamedPipeClientStream pipe) : base(pipe)
{
}
protected override void Handle(BinaryReader reader, MessageType messageType)
{
switch (messageType)
{
case MessageType.JoinGame:
{
Handle(JoinGameMessage.Deserialize(reader));
break;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null);
}
}
}
private static void Handle(in JoinGameMessage message)
{
var (address, port, gameCode) = message;
Dispatcher.Instance.Enqueue(() =>
{
var gameCodeText = gameCode == InnerNetServer.LocalGameId ? "<local>" : GameCode.IntToGameName(gameCode);
Info($"Joining {gameCodeText} on {address}:{port}");
if (gameCode == InnerNetServer.LocalGameId)
{
AmongUsClient.Instance.NetworkMode = NetworkModes.LocalGame;
AmongUsClient.Instance.GameId = gameCode;
AmongUsClient.Instance.StartCoroutine(AmongUsClient.Instance.CoConnectToGameServer(MatchMakerModes.Client, address, port, null));
}
else
{
AmongUsClient.Instance.StartCoroutine(AmongUsClient.Instance.CoJoinOnlineGameDirect(gameCode, address, port, null));
}
});
}
public void SendRequestJoin()
{
Write(default(RequestJoinGameMessage));
}
public static bool TryConnect([NotNullWhen(true)] out AutoJoinClientConnection? client)
{
var pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.InOut, PipeOptions.Asynchronous);
try
{
pipeClient.Connect(100);
client = new AutoJoinClientConnection(pipeClient);
return true;
}
catch (TimeoutException)
{
pipeClient.Dispose();
client = null;
return false;
}
}
}
@@ -1,61 +0,0 @@
using System;
using System.IO;
using System.IO.Pipes;
using System.Threading.Tasks;
using Reactor.Debugger.AutoJoin.Messages;
namespace Reactor.Debugger.AutoJoin;
internal abstract class AutoJoinConnection : IDisposable
{
private readonly BinaryWriter _writer;
protected AutoJoinConnection(PipeStream pipe)
{
_writer = new BinaryWriter(pipe);
Task.Run(() =>
{
try
{
var reader = new BinaryReader(pipe);
while (pipe.IsConnected)
{
try
{
var messageType = (MessageType) reader.ReadByte();
Debug($"Received {messageType}");
Handle(reader, messageType);
}
catch (EndOfStreamException)
{
break;
}
}
pipe.Dispose();
Disconnected?.Invoke();
}
catch (Exception e)
{
Error(e);
}
});
}
public event Action? Disconnected;
protected abstract void Handle(BinaryReader reader, MessageType messageType);
public void Write<T>(in T message) where T : IMessage<T>
{
Debug($"Writing {message}");
_writer.Write(message);
}
public void Dispose()
{
_writer.Dispose();
}
}
@@ -1,113 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO.Pipes;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using InnerNet;
using Reactor.Debugger.AutoJoin.Messages;
namespace Reactor.Debugger.AutoJoin;
internal sealed class AutoJoinConnectionListener : IDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly Mutex _mutex;
private AutoJoinConnectionListener(Mutex mutex)
{
_mutex = mutex;
Task.Run(async () =>
{
while (!_cancellationTokenSource.IsCancellationRequested)
{
try
{
Info("Listening for connections");
var pipeServer = new NamedPipeServerStream(
AutoJoinClientConnection.PipeName,
PipeDirection.InOut,
NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Byte,
PipeOptions.Asynchronous
);
try
{
await pipeServer.WaitForConnectionAsync(_cancellationTokenSource.Token);
}
catch (OperationCanceledException)
{
pipeServer.Dispose();
break;
}
Info("Client connected");
var client = new AutoJoinServerConnection(pipeServer);
Clients.Add(client);
client.Disconnected += () =>
{
Clients.Remove(client);
client.Dispose();
};
}
catch (Exception e)
{
Error(e);
}
}
Info("Stopped");
Stopped?.Invoke();
});
}
public event Action? Stopped;
public List<AutoJoinServerConnection> Clients { get; } = new();
public void Dispose()
{
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
foreach (var client in Clients)
{
client.Dispose();
}
Clients.Clear();
_mutex.Dispose();
}
public void SendJoinMe(InnerNetClient innerNetClient)
{
var joinGameMessage = JoinGameMessage.From(innerNetClient);
foreach (var client in Clients)
{
client.Write(joinGameMessage);
}
}
public static bool TryStart([NotNullWhen(true)] out AutoJoinConnectionListener? connectionListener)
{
var mutex = new Mutex(false, $@"Global\{AutoJoinClientConnection.PipeName}");
if (mutex.WaitOne(100))
{
connectionListener = new AutoJoinConnectionListener(mutex);
return true;
}
mutex.Dispose();
connectionListener = null;
return false;
}
}
@@ -1,66 +0,0 @@
using HarmonyLib;
using InnerNet;
namespace Reactor.Debugger.AutoJoin;
internal static class AutoJoinConnectionManager
{
public static AutoJoinConnectionListener? Server { get; set; }
public static AutoJoinClientConnection? Client { get; set; }
public static void StartOrConnect()
{
if (AutoJoinConnectionListener.TryStart(out var connectionListener))
{
Info("Started an AutoJoin session");
Server = connectionListener;
Server.Stopped += () =>
{
if (Server == connectionListener)
{
Server = null;
}
};
}
else if (AutoJoinClientConnection.TryConnect(out var client))
{
Info("Connected to an AutoJoin session");
Client = client;
client.Disconnected += () =>
{
if (Client == client)
{
Client = null;
Info("Disconnected from an AutoJoin session, trying to reconnect");
StartOrConnect();
}
};
}
else
{
Error("Failed to start or connect to an AutoJoin session");
}
}
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.Start))]
public static class ConnectPatch
{
public static void Postfix(InnerNetClient __instance)
{
if (!DebuggerConfig.JoinGameOnStart.Value) return;
if (__instance.TryCast<AmongUsClient>() is { } amongUsClient)
{
if (Server != null)
{
amongUsClient.StartCoroutine(amongUsClient.CoCreateOnlineGame());
}
else if (Client is { } client)
{
client.SendRequestJoin();
}
}
}
}
}
@@ -1,38 +0,0 @@
using System;
using System.IO;
using System.IO.Pipes;
using Reactor.Debugger.AutoJoin.Messages;
namespace Reactor.Debugger.AutoJoin;
internal sealed class AutoJoinServerConnection : AutoJoinConnection
{
public AutoJoinServerConnection(NamedPipeServerStream pipe) : base(pipe)
{
}
protected override void Handle(BinaryReader reader, MessageType messageType)
{
switch (messageType)
{
case MessageType.RequestJoinGame:
{
Handle(RequestJoinGameMessage.Deserialize(reader));
break;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(messageType), messageType, null);
}
}
}
private void Handle(in RequestJoinGameMessage message)
{
if (AmongUsClient.Instance.AmConnected)
{
Write(JoinGameMessage.From(AmongUsClient.Instance));
}
}
}
@@ -1,12 +0,0 @@
using System.IO;
namespace Reactor.Debugger.AutoJoin.Messages;
internal static class Extensions
{
public static void Write<T>(this BinaryWriter writer, in T message) where T : IMessage<T>
{
writer.Write((byte) T.Type);
message.Serialize(writer);
}
}
@@ -1,15 +0,0 @@
#pragma warning disable CA2252 // TODO Remove after BepInEx updates the .NET version
using System.IO;
namespace Reactor.Debugger.AutoJoin.Messages;
internal interface IMessage<TSelf> where TSelf : IMessage<TSelf>
{
static abstract MessageType Type { get; }
void Serialize(BinaryWriter writer);
static abstract TSelf Deserialize(BinaryReader reader);
string ToString();
}
@@ -1,40 +0,0 @@
using System.IO;
using InnerNet;
namespace Reactor.Debugger.AutoJoin.Messages;
internal readonly record struct JoinGameMessage(
string Address,
ushort Port,
int GameCode
) : IMessage<JoinGameMessage>
{
public static MessageType Type => MessageType.JoinGame;
public void Serialize(BinaryWriter writer)
{
writer.Write(Address);
writer.Write(Port);
writer.Write(GameCode);
}
public static JoinGameMessage Deserialize(BinaryReader reader)
{
return new JoinGameMessage
{
Address = reader.ReadString(),
Port = reader.ReadUInt16(),
GameCode = reader.ReadInt32(),
};
}
public static JoinGameMessage From(InnerNetClient innerNetClient)
{
return new JoinGameMessage
{
Address = innerNetClient.networkAddress,
Port = (ushort) innerNetClient.networkPort,
GameCode = innerNetClient.GameId,
};
}
}
@@ -1,7 +0,0 @@
namespace Reactor.Debugger.AutoJoin.Messages;
internal enum MessageType : byte
{
JoinGame,
RequestJoinGame,
}
@@ -1,17 +0,0 @@
using System.IO;
namespace Reactor.Debugger.AutoJoin.Messages;
internal readonly record struct RequestJoinGameMessage : IMessage<RequestJoinGameMessage>
{
public static MessageType Type => MessageType.RequestJoinGame;
public void Serialize(BinaryWriter writer)
{
}
public static RequestJoinGameMessage Deserialize(BinaryReader reader)
{
return default;
}
}
-26
View File
@@ -1,26 +0,0 @@
using BepInEx.Configuration;
namespace Reactor.Debugger;
internal static class DebuggerConfig
{
public const string FeaturesSection = "Features";
public const string AutoJoinSection = "AutoJoin";
public static ConfigEntry<bool> DisableGameEnd { get; private set; } = null!;
public static ConfigEntry<bool> RedirectLogger { get; private set; } = null!;
public static ConfigEntry<bool> AutoPlayAgain { get; private set; } = null!;
public static ConfigEntry<bool> DisableTimeout { get; private set; } = null!;
public static ConfigEntry<bool> JoinGameOnStart { get; private set; } = null!;
public static void Bind(ConfigFile config)
{
DisableGameEnd = config.Bind(FeaturesSection, nameof(DisableGameEnd), false, "Stops the game from ending regardless of conditions");
RedirectLogger = config.Bind(FeaturesSection, nameof(RedirectLogger), false, "Redirect base game Logger calls into BepInEx logging");
AutoPlayAgain = config.Bind(FeaturesSection, nameof(AutoPlayAgain), true, "Automatically calls Play Again after game ends");
DisableTimeout = config.Bind(FeaturesSection, nameof(DisableTimeout), false, "Disable the network disconnection timeout");
JoinGameOnStart = config.Bind(AutoJoinSection, nameof(JoinGameOnStart), false, "Automatically hosts/joins a game on start");
}
}
+97 -9
View File
@@ -1,10 +1,15 @@
global using static Reactor.Utilities.Logger<Reactor.Debugger.DebuggerPlugin>;
using System;
using System.Linq;
using AmongUs.Data;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Reactor.Debugger.AutoJoin;
using Reactor.Debugger.Patches;
using Reactor.Debugger.Window;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using InnerNet;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.ImGui;
using UnityEngine;
namespace Reactor.Debugger;
@@ -14,17 +19,100 @@ namespace Reactor.Debugger;
public partial class DebuggerPlugin : BasePlugin
{
public Harmony Harmony { get; } = new(Id);
public DebuggerComponent Component { get; private set; } = null!;
public override void Load()
{
DebuggerConfig.Bind(Config);
Component = this.AddComponent<DebuggerComponent>();
this.AddComponent<DebuggerWindow>();
GameOptionsPatches.Initialize();
GameOptionsData.MaxImpostors = GameOptionsData.RecommendedImpostors = Enumerable.Repeat((int) byte.MaxValue, byte.MaxValue).ToArray();
GameOptionsData.MinPlayers = Enumerable.Repeat(1, 4).ToArray();
Harmony.PatchAll();
}
AutoJoinConnectionManager.StartOrConnect();
[RegisterInIl2Cpp]
public class DebuggerComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public bool DisableGameEnd { get; set; }
[HideFromIl2Cpp]
public DragWindow TestWindow { get; }
public DebuggerComponent(IntPtr ptr) : base(ptr)
{
TestWindow = new DragWindow(new Rect(20, 20, 0, 0), "Debugger", () =>
{
GUILayout.Label("Name: " + DataManager.Player.Customization.Name);
DisableGameEnd = GUILayout.Toggle(DisableGameEnd, "Disable game end");
if (ShipStatus.Instance && AmongUsClient.Instance.AmHost)
{
if (GUILayout.Button("Force game end"))
{
ShipStatus.Instance.enabled = false;
ShipStatus.RpcEndGame(GameOverReason.ImpostorDisconnect, false);
}
if (GUILayout.Button("Call a meeting"))
{
PlayerControl.LocalPlayer.CmdReportDeadBody(null);
}
}
if (TutorialManager.InstanceExists && PlayerControl.LocalPlayer)
{
var data = PlayerControl.LocalPlayer.Data;
var newIsImpostor = GUILayout.Toggle(data.Role.IsImpostor, "Is Impostor");
if (data.Role.IsImpostor != newIsImpostor)
{
PlayerControl.LocalPlayer.RpcSetRole(newIsImpostor ? RoleTypes.Impostor : RoleTypes.Crewmate);
}
if (GUILayout.Button("Spawn a dummy"))
{
var playerControl = Instantiate(TutorialManager.Instance.PlayerPrefab);
var i = playerControl.PlayerId = (byte) GameData.Instance.GetAvailableId();
GameData.Instance.AddPlayer(playerControl);
AmongUsClient.Instance.Spawn(playerControl, -2, SpawnFlags.None);
playerControl.transform.position = PlayerControl.LocalPlayer.transform.position;
playerControl.GetComponent<DummyBehaviour>().enabled = true;
playerControl.NetTransform.enabled = false;
playerControl.SetName($"{TranslationController.Instance.GetString(StringNames.Dummy, Array.Empty<Il2CppSystem.Object>())} {i}");
var color = (byte) (i % Palette.PlayerColors.Length);
playerControl.SetColor(color);
playerControl.SetHat(HatManager.Instance.allHats[i % HatManager.Instance.allHats.Count].ProdId, playerControl.Data.DefaultOutfit.ColorId);
playerControl.SetPet(HatManager.Instance.allPets[i % HatManager.Instance.allPets.Count].ProdId);
playerControl.SetSkin(HatManager.Instance.allSkins[i % HatManager.Instance.allSkins.Count].ProdId, color);
GameData.Instance.RpcSetTasks(playerControl.PlayerId, new Il2CppStructArray<byte>(0));
}
}
if (PlayerControl.LocalPlayer)
{
var position = PlayerControl.LocalPlayer.transform.position;
GUILayout.Label($"x: {position.x}");
GUILayout.Label($"y: {position.y}");
}
})
{
Enabled = false,
};
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F1))
{
TestWindow.Enabled = !TestWindow.Enabled;
}
}
private void OnGUI()
{
TestWindow.OnGUI();
}
}
}
+70
View File
@@ -0,0 +1,70 @@
using System.Linq;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Reactor.Utilities;
using UnityEngine;
namespace Reactor.Debugger;
internal static class Patches
{
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class UpdatePatch
{
public static void Prefix(GameStartManager __instance)
{
__instance.MinPlayers = 1;
}
}
[HarmonyPatch(typeof(GameStartManager), nameof(GameStartManager.Update))]
public static class CountdownPatch
{
public static void Prefix(GameStartManager __instance)
{
__instance.countDownTimer = 0;
}
}
[HarmonyPatch(typeof(StatsManager), nameof(StatsManager.AmBanned), MethodType.Getter)]
public static class AmBannedPatch
{
public static void Postfix(out bool __result)
{
__result = false;
}
}
[HarmonyPatch(typeof(ShipStatus), nameof(ShipStatus.CheckEndCriteria))]
[HarmonyPriority(Priority.First)]
public static class CheckEndCriteriaPatch
{
public static bool Prefix()
{
return !PluginSingleton<DebuggerPlugin>.Instance.Component.DisableGameEnd;
}
}
[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.Start))]
public static class GameSettingMenuPatch
{
public static void Prefix(GameSettingMenu __instance)
{
// Unlocks map/impostor amount changing in online (for testing on your custom servers)
__instance.HideForOnline = new Il2CppReferenceArray<Transform>(0);
}
}
[HarmonyPatch(typeof(GameOptionsMenu), nameof(GameOptionsMenu.Start))]
[HarmonyPriority(Priority.First)]
public static class GameOptionsMenuPatch
{
public static void Postfix(GameOptionsMenu __instance)
{
__instance.Children
.Single(o => o.Title == StringNames.GameNumImpostors)
.Cast<NumberOption>()
.ValidRange = new FloatRange(0, byte.MaxValue);
}
}
}
@@ -1,14 +0,0 @@
using HarmonyLib;
namespace Reactor.Debugger.Patches;
[HarmonyPatch(typeof(EndGameNavigation), nameof(EndGameNavigation.ShowDefaultNavigation))]
internal static class AutoPlayAgainPatch
{
public static void Postfix(EndGameNavigation __instance)
{
if (!DebuggerConfig.AutoPlayAgain.Value) return;
__instance.NextGame();
}
}
@@ -1,18 +0,0 @@
using HarmonyLib;
namespace Reactor.Debugger.Patches;
[HarmonyPatch]
[HarmonyPriority(Priority.First)]
internal static class DisableGameEndPatch
{
private static bool Enabled => DebuggerConfig.DisableGameEnd.Value;
[HarmonyPatch(typeof(LogicGameFlow), nameof(LogicGameFlow.CheckEndCriteria))]
[HarmonyPatch(typeof(LogicGameFlowNormal), nameof(LogicGameFlow.CheckEndCriteria))]
[HarmonyPatch(typeof(LogicGameFlowHnS), nameof(LogicGameFlow.CheckEndCriteria))]
public static bool Prefix()
{
return !Enabled;
}
}
@@ -1,27 +0,0 @@
using HarmonyLib;
using Hazel.Udp;
namespace Reactor.Debugger.Patches;
[HarmonyPatch]
internal static class DisableTimeoutPatch
{
private static bool Enabled => DebuggerConfig.DisableTimeout.Value;
[HarmonyPatch(typeof(UdpConnection), nameof(UdpConnection.HandleKeepAlive))]
[HarmonyPrefix]
public static bool DisableKeepAlive()
{
return !Enabled;
}
[HarmonyPatch(typeof(UnityUdpClientConnection), nameof(UnityUdpClientConnection.ConnectAsync))]
[HarmonyPostfix]
public static void DisableTimeout(UnityUdpClientConnection __instance)
{
if (!Enabled) return;
__instance.DisconnectTimeoutMs = int.MaxValue;
__instance.ResendLimit = 0;
}
}
@@ -1,68 +0,0 @@
using System.Linq;
using AmongUs.GameOptions;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Reflection;
using UnityEngine;
namespace Reactor.Debugger.Patches;
[HarmonyPatch]
internal static class GameOptionsPatches
{
public static void Initialize()
{
var maxImpostors = (Il2CppStructArray<int>) Enumerable.Repeat((int) byte.MaxValue, byte.MaxValue).ToArray();
NormalGameOptionsV09.MaxImpostors = maxImpostors;
NormalGameOptionsV09.MaxImpostors = maxImpostors;
var minPlayers = (Il2CppStructArray<int>) Enumerable.Repeat(1, byte.MaxValue).ToArray();
NormalGameOptionsV09.MinPlayers = minPlayers;
NormalGameOptionsV09.MinPlayers = minPlayers;
}
[HarmonyPatch(typeof(GameSettingMenu), nameof(GameSettingMenu.Start))]
[HarmonyPrefix]
public static void UnlockAllOptions(GameSettingMenu __instance)
{
__instance.GameSettingsTab.HideForOnline = new Il2CppReferenceArray<Transform>(0);
}
[HarmonyPatch(typeof(NumberOption), nameof(NumberOption.SetUpFromData))]
[HarmonyPostfix]
public static void UnlockOptionRange(NumberOption __instance)
{
__instance.ValidRange.min = float.MinValue;
__instance.ValidRange.max = float.MaxValue;
}
[HarmonyPatch(typeof(CreateOptionsPicker), nameof(CreateOptionsPicker.SetImpostorButtons))]
public static class DisableImpostorCountReset
{
private static readonly MethodInfo _refreshMethod = Il2CppType.Of<CreateOptionsPicker>().GetMethod("Refresh", BindingFlags.Public | BindingFlags.Instance);
public static bool Prefix()
{
foreach (var stackFrame in new Il2CppSystem.Diagnostics.StackTrace().GetFrames())
{
if (_refreshMethod.Equals(stackFrame.GetMethod()))
{
return false;
}
}
return true;
}
}
[HarmonyPatch(typeof(CrewVisualizer), nameof(CrewVisualizer.SetCrewSize))]
[HarmonyPrefix]
public static void SetCrewSizePatch(int numPlayers, ref int numImpostors)
{
if (numImpostors >= numPlayers)
{
numImpostors = 0;
}
}
}
@@ -1,21 +0,0 @@
using HarmonyLib;
namespace Reactor.Debugger.Patches;
[HarmonyPatch(typeof(GameStartManager))]
internal static class GameStartManagerPatches
{
[HarmonyPatch(nameof(GameStartManager.Start))]
[HarmonyPrefix]
public static void StartPatch(GameStartManager __instance)
{
__instance.MinPlayers = 1;
}
[HarmonyPatch(nameof(GameStartManager.Update))]
[HarmonyPrefix]
public static void UpdatePatch(GameStartManager __instance)
{
__instance.countDownTimer = 0;
}
}
@@ -1,39 +0,0 @@
using System;
using System.Net;
using HarmonyLib;
using InnerNet;
namespace Reactor.Debugger.Patches;
[HarmonyPatch]
internal static class RandomizeFreeplayServerPortPatch
{
private static ushort? _lastPort;
[HarmonyPatch(typeof(InnerNetServer), nameof(InnerNetServer.StartAsLocalServer))]
public static class StartServerPatch
{
public static void Prefix(InnerNetServer __instance)
{
var port = (ushort) Random.Shared.Next(1024, IPEndPoint.MaxPort);
_lastPort = port;
__instance.Port = port;
}
public static void Postfix(InnerNetServer __instance)
{
__instance.Port = Constants.GamePlayPort;
}
}
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.SetEndpoint))]
[HarmonyPrefix]
public static void SetEndpointPatch(InnerNetClient __instance, string addr, ref ushort port)
{
if (_lastPort != null && __instance.NetworkMode == NetworkModes.FreePlay)
{
port = _lastPort.Value;
_lastPort = null;
}
}
}
@@ -1,114 +0,0 @@
using System.Globalization;
using System.Text;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
namespace Reactor.Debugger.Patches;
[HarmonyPatch(typeof(Logger))]
internal static class RedirectLoggerPatch
{
private static readonly ManualLogSource _log = BepInEx.Logging.Logger.CreateLogSource("Among Us");
private static bool Enabled => DebuggerConfig.RedirectLogger.Value;
private static void Log(Logger logger, LogLevel level, Il2CppStringArray? path, Il2CppSystem.Object message, UnityEngine.Object? context = null)
{
var finalMessage = new StringBuilder();
if (logger.category != Logger.Category.None) finalMessage.Append(CultureInfo.InvariantCulture, $"[{logger.category}] ");
if (logger.subCategories != null)
{
foreach (var subCategory in logger.subCategories)
{
finalMessage.Append(CultureInfo.InvariantCulture, $"[{subCategory}] ");
}
}
if (path != null)
{
foreach (var p in path)
{
finalMessage.Append(CultureInfo.InvariantCulture, $"[{p}] ");
}
}
if (context != null) finalMessage.Append(CultureInfo.InvariantCulture, $"[{context.name} ({context.GetIl2CppType().FullName})] ");
finalMessage.Append(message.ToString());
_log.Log(level, finalMessage);
}
[HarmonyPatch(nameof(Logger.Debug), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool DebugPatch(Logger __instance, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Debug, null, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Info), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool InfoPatch(Logger __instance, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Info, null, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Warning), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool WarningPatch(Logger __instance, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Warning, null, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Error), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool ErrorPatch(Logger __instance, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Error, null, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Debug), typeof(Il2CppStringArray), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool DebugPatch(Logger __instance, Il2CppStringArray? path, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Debug, path, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Info), typeof(Il2CppStringArray), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool InfoPatch(Logger __instance, Il2CppStringArray? path, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Info, path, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Warning), typeof(Il2CppStringArray), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool WarningPatch(Logger __instance, Il2CppStringArray? path, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Warning, path, message, context);
return false;
}
[HarmonyPatch(nameof(Logger.Error), typeof(Il2CppStringArray), typeof(Il2CppSystem.Object), typeof(UnityEngine.Object))]
[HarmonyPrefix]
public static bool ErrorPatch(Logger __instance, Il2CppStringArray? path, Il2CppSystem.Object message, UnityEngine.Object? context)
{
if (!Enabled) return true;
Log(__instance, LogLevel.Error, path, message, context);
return false;
}
}
-49
View File
@@ -1,49 +0,0 @@
using System;
using System.Collections;
using Il2CppInterop.Runtime;
using InnerNet;
namespace Reactor.Debugger.Utilities;
internal static class Extensions
{
public static IEnumerator CoCreateLocalGame(this AmongUsClient client, bool isFreePlay = false)
{
try
{
if (isFreePlay)
{
client.NetworkMode = NetworkModes.FreePlay;
InnerNetServer.Instance.StartAsLocalServer();
client.MainMenuScene = "MainMenu";
client.OnlineScene = "Tutorial";
}
else
{
client.NetworkMode = NetworkModes.LocalGame;
InnerNetServer.Instance.StartAsServer();
client.MainMenuScene = "MatchMaking";
client.OnlineScene = "OnlineGame";
}
client.SetEndpoint(Constants.LocalNetAddress, Constants.GamePlayPort, false);
}
catch (Il2CppException e)
{
Error(e);
DisconnectPopup.Instance.ShowCustom(e.Message[..e.Message.IndexOf("\n--- BEGIN IL2CPP STACK TRACE ---\n", StringComparison.Ordinal)]);
MatchMaker.Instance.NotConnecting();
yield break;
}
client.Connect(MatchMakerModes.HostAndClient, null);
yield return client.WaitForConnectionOrFail();
DestroyableSingleton<MatchMaker>.Instance.NotConnecting();
}
}
-112
View File
@@ -1,112 +0,0 @@
using System;
using System.Collections;
using System.Linq;
using AmongUs.Data;
using BepInEx.Unity.IL2CPP.Utils;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.InteropTypes;
using Reactor.Debugger.Utilities;
using Reactor.Debugger.Window.Tabs;
using Reactor.Utilities.Attributes;
using Reactor.Utilities.ImGui;
using UnityEngine;
namespace Reactor.Debugger.Window;
[RegisterInIl2Cpp]
internal sealed class DebuggerWindow : MonoBehaviour
{
private readonly DragWindow _window;
[HideFromIl2Cpp]
public BaseTab[] Tabs { get; } =
{
new ConfigTab(),
new GameTab(),
new AutoJoinTab(),
};
[HideFromIl2Cpp]
public BaseTab SelectedTab { get; private set; }
public DebuggerWindow(IntPtr ptr) : base(ptr)
{
SelectedTab = Tabs[0];
_window = new DragWindow(new Rect(20, 20, 0, 0), "Reactor.Debugger", () =>
{
var clientName = DataManager.Player.Customization.Name;
if (AmongUsClient.Instance && AmongUsClient.Instance.AmHost) clientName += " (host)";
GUILayout.Label("Name: " + clientName);
if (GUILayout.Button("Hard crash"))
{
static unsafe void Corrupt(Il2CppObjectBase o)
{
var x = (IntPtr*) o.Pointer;
x[0] = (IntPtr) 0xF00;
}
static IEnumerator CoCrash()
{
if (!PlayerControl.LocalPlayer || !ShipStatus.Instance)
{
yield return AmongUsClient.Instance.CoCreateLocalGame(true);
while (!PlayerControl.LocalPlayer || !ShipStatus.Instance)
{
yield return null;
}
}
var usable = FindObjectsOfType<MonoBehaviour>().First(x => x.TryCast<IUsable>() != null);
if (!usable)
{
Error("Failed to find an IUsable to crash with");
yield break;
}
var cloned = Instantiate(usable, PlayerControl.LocalPlayer.transform.position, default);
Warning($"Crashing with {cloned.name}");
Corrupt(cloned);
}
this.StartCoroutine(CoCrash());
}
GUILayout.BeginHorizontal();
{
foreach (var tab in Tabs)
{
if (GUILayout.Toggle(tab == SelectedTab, tab.Name, new GUIStyle(GUI.skin.button)))
{
SelectedTab = tab;
}
}
}
GUILayout.EndHorizontal();
GUILayout.Space(5f);
SelectedTab.OnGUI();
})
{
Enabled = false,
};
}
public void Update()
{
if (Input.GetKeyDown(KeyCode.F1))
{
_window.Enabled = !_window.Enabled;
}
}
public void OnGUI()
{
_window.OnGUI();
}
}
@@ -1,68 +0,0 @@
using BepInEx.Unity.IL2CPP.Utils;
using Reactor.Debugger.AutoJoin;
using Reactor.Debugger.Utilities;
using UnityEngine;
namespace Reactor.Debugger.Window.Tabs;
internal sealed class AutoJoinTab : BaseTab
{
public override string Name => "AutoJoin";
public override void OnGUI()
{
if (AutoJoinConnectionManager.Server is { } server)
{
GUILayout.Label($"Hosting ({server.Clients.Count} clients)");
if (GUILayout.Button("Stop"))
{
server.Dispose();
}
if (AmongUsClient.Instance)
{
if (GUILayout.Button("Create an online game"))
{
AmongUsClient.Instance.StartCoroutine(AmongUsClient.Instance.CoCreateOnlineGame());
}
if (GUILayout.Button("Create a local game"))
{
AmongUsClient.Instance.StartCoroutine(AmongUsClient.Instance.CoCreateLocalGame());
}
if (
AmongUsClient.Instance.AmConnected &&
AmongUsClient.Instance.NetworkMode != NetworkModes.FreePlay &&
GUILayout.Button("Join me")
)
{
server.SendJoinMe(AmongUsClient.Instance);
}
}
}
else if (AutoJoinConnectionManager.Client is { } client)
{
GUILayout.Label("Connected");
if (GUILayout.Button("Disconnect"))
{
AutoJoinConnectionManager.Client = null;
client.Dispose();
}
if (GUILayout.Button("Request join"))
{
client.SendRequestJoin();
}
}
else
{
if (GUILayout.Button("Connect"))
{
AutoJoinConnectionManager.StartOrConnect();
}
}
}
}
-8
View File
@@ -1,8 +0,0 @@
namespace Reactor.Debugger.Window.Tabs;
internal abstract class BaseTab
{
public abstract string Name { get; }
public abstract void OnGUI();
}
-29
View File
@@ -1,29 +0,0 @@
using System.Linq;
using BepInEx.Configuration;
using Reactor.Utilities;
using UnityEngine;
namespace Reactor.Debugger.Window.Tabs;
internal sealed class ConfigTab : BaseTab
{
public override string Name => "Config";
public override void OnGUI()
{
var configs = PluginSingleton<ReactorPlugin>.Instance.Config.Concat(PluginSingleton<DebuggerPlugin>.Instance.Config);
foreach (var section in configs.GroupBy(e => e.Key.Section))
{
GUILayout.Label(section.Key);
foreach (var (definition, entry) in section)
{
if (entry is ConfigEntry<bool> booleanEntry)
{
booleanEntry.Value = GUILayout.Toggle(booleanEntry.Value, definition.Key);
}
}
}
}
}
-97
View File
@@ -1,97 +0,0 @@
using AmongUs.GameOptions;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Reactor.Debugger.Window.Tabs;
internal sealed class GameTab : BaseTab
{
public override string Name => "Game";
public override void OnGUI()
{
var localPlayer = PlayerControl.LocalPlayer;
if (!localPlayer)
{
return;
}
var amHost = AmongUsClient.Instance.AmHost;
var position = localPlayer.transform.position;
GUILayout.Label($"Position: ({position.x:F3}, {position.y:F3})");
var physics = localPlayer.MyPhysics;
GUILayout.Label($"Speed: {physics.Speed}");
physics.Speed = GUILayout.HorizontalSlider(physics.Speed, 0, 25);
localPlayer.Collider.enabled = GUILayout.Toggle(localPlayer.Collider.enabled, "Collisions");
if (ShipStatus.Instance)
{
if (amHost && GUILayout.Button("Force game end"))
{
ShipStatus.Instance.enabled = false;
GameManager.Instance.RpcEndGame(GameOverReason.ImpostorDisconnect, false);
}
if (MeetingHud.Instance)
{
if (GUILayout.Button("Stop the meeting"))
{
MeetingHud.Instance.RpcClose();
}
}
else
{
if (GUILayout.Button("Call a meeting"))
{
localPlayer.CmdReportDeadBody(null);
}
}
if (TutorialManager.InstanceExists)
{
var newIsImpostor = GUILayout.Toggle(localPlayer.Data.Role.IsImpostor, "Is Impostor");
if (localPlayer.Data.Role.IsImpostor != newIsImpostor)
{
localPlayer.RpcSetRole(newIsImpostor ? RoleTypes.Impostor : RoleTypes.Crewmate);
}
if (GUILayout.Button("Spawn a dummy"))
{
SpawnDummy();
}
}
}
}
private static void SpawnDummy()
{
var playerControl = Object.Instantiate(AmongUsClient.Instance.PlayerPrefab);
var playerId = playerControl.PlayerId = (byte) GameData.Instance.GetAvailableId();
var data = GameData.Instance.AddDummy(playerControl);
AmongUsClient.Instance.Spawn(data);
AmongUsClient.Instance.Spawn(playerControl);
playerControl.isDummy = true;
playerControl.transform.position = PlayerControl.LocalPlayer.transform.position;
playerControl.GetComponent<DummyBehaviour>().enabled = true;
playerControl.NetTransform.enabled = false;
playerControl.SetName($"{TranslationController.Instance.GetString(StringNames.Dummy)} {playerId}");
var color = (byte) (playerId % Palette.PlayerColors.Length);
playerControl.SetColor(color);
playerControl.SetHat(HatManager.Instance.allHats[playerId % HatManager.Instance.allHats.Count].ProdId, playerControl.Data.DefaultOutfit.ColorId);
playerControl.SetPet(HatManager.Instance.allPets[playerId % HatManager.Instance.allPets.Count].ProdId);
playerControl.SetSkin(HatManager.Instance.allSkins[playerId % HatManager.Instance.allSkins.Count].ProdId, color);
playerControl.SetVisor(HatManager.Instance.allVisors[playerId % HatManager.Instance.allVisors.Count].ProdId, color);
playerControl.SetNamePlate(HatManager.Instance.allNamePlates[playerId % HatManager.Instance.allNamePlates.Count].ProdId);
data.PlayerLevel = playerId;
data.RpcSetTasks(new Il2CppStructArray<byte>(0));
}
}
+110 -123
View File
@@ -4,9 +4,9 @@
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2025.4.15, )",
"resolved": "2025.4.15",
"contentHash": "R3RxzHGZOGUJ9nMwrP0cjS6g+sh60QUU506Mo47lh17155enUjH6PtErijihSoU7t3aQpzCIyC67W3XrrHhH4g=="
"requested": "[2022.10.25, )",
"resolved": "2022.10.25",
"contentHash": "PWgkH/VvMlShVhZB8G432q0tnMaNVZrbIdbEMCZN/fETUlT/ch+qQj4PdTcZhPHREbnJHH3ijHxlca1d7QMBcQ=="
},
"BepInEx.AutoPlugin": {
"type": "Direct",
@@ -16,111 +16,64 @@
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.1.0-rc.1, )",
"resolved": "2.1.0-rc.1",
"contentHash": "WI/7TbJwWl5P4B6UXGtKI1VMe6fA6h3fcbp3ZjJKqOBQ5MJfDMmeVB4fb+RW1tUQdxnlSWV3Ul62PHFyTqp4PA=="
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.735, )",
"resolved": "6.0.0-be.735",
"contentHash": "2+eFJGKMR1GFPeU9wuF+TVrMANIaWIc/6N9e8x4b7b/fNiY9B6vicYNiMDb2deYQpWZtOei+2btnar5dDE5BPg==",
"requested": "[6.0.0-be.662, )",
"resolved": "6.0.0-be.662",
"contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.735",
"BepInEx.Unity.Common": "6.0.0-be.735",
"HarmonyX": "2.10.2",
"Iced": "1.21.0",
"Il2CppInterop.Generator": "1.4.6-ci.426",
"Il2CppInterop.HarmonySupport": "1.4.6-ci.426",
"Il2CppInterop.Runtime": "1.4.6-ci.426",
"MonoMod.RuntimeDetour": "22.7.31.1",
"Samboy063.Cpp2IL.Core": "2022.1.0-pre-release.19"
"BepInEx.Core": "6.0.0-be.662",
"BepInEx.Unity.Common": "6.0.0-be.662",
"HarmonyX": "2.10.0",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.3.0",
"Il2CppInterop.HarmonySupport": "1.3.0",
"Il2CppInterop.Runtime": "1.3.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.556, )",
"resolved": "1.2.0-beta.556",
"contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.556"
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AsmResolver": {
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "M5btCR/rmrx32jZsoN6CLQ/VQk8lN8hvPb6lgojua7pjNoo7StAl92koMC8qz4vzZyH2CNqxLSDoswRvyyK/vA=="
},
"AsmResolver.DotNet": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "PTq8nNQvhgTxF1iARCknffCsu7Iq9B0kN7TVC8iMaU7uEYog3xvVqH/0+TreY8GW74/+MqhZt/yEFsvS4oAduQ==",
"dependencies": {
"AsmResolver.PE": "6.0.0-beta.1"
}
},
"AsmResolver.PE": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "KadLvx/zzFCJyF+E4jG6jPE1d0iJquzL6+hm8GBivBAs6nwHC8s6g4c857QwQCzXMWza6Vz5Q+3hFiNuOfKaWQ==",
"dependencies": {
"AsmResolver.PE.File": "6.0.0-beta.1"
}
},
"AsmResolver.PE.File": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "+lusB9UMHevI5aQsu73NQ1ctPMLFvyHAsEf8vjaJ/py+kX1DkU0JkbERtBRmaf58/hBZ7cyrE7gFnjoo7Bbg7A==",
"dependencies": {
"AsmResolver": "6.0.0-beta.1"
}
},
"AssetRipper.CIL": {
"type": "Transitive",
"resolved": "1.1.2",
"contentHash": "BRPcHORadIzSFkrVOvGkSs54j19mQdXH8dmRTVM51mS8MZLSbTpi9CDPpnWN2IdDsILUrAqbPUFo3zJodYxErw==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1"
}
},
"AssetRipper.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "wOr5PQPL/2ZfD7+ebt6cpRbUhSzSY5nlHGHjjzuQRiU5zkQlqQNwWDLX0M3smrm5IkaDvONkmDjFMKTlZJmyuQ=="
},
"AssetRipper.Primitives": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "djZbN/+EXmI+Oia9Pm0LyjZVCPLf60TPSL5rGb7mBEYM5F4CN3nPFXvl2yA5LanPZoHS1Yq7PghGUmkP7Pv9RQ=="
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "FuHm9UCzjSKeiZJc3IF70Fiuqi+FynRn62PwBoOeZcHK3/qm+vl1YwbZyFlmUyf45g+UKxg2Td40iZGx88LVAQ==",
"resolved": "6.0.0-be.662",
"contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==",
"dependencies": {
"HarmonyX": "2.10.2",
"MonoMod.Utils": "22.7.31.1",
"HarmonyX": "2.10.0",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "vmK//OBSr+jotqTk//HSdvHtMFTKu+NlQkiEsvr0dZApTVmQM2AgpVMhEAakQPmrSsM6LRJIHCBcLFO1ypfMPQ==",
"resolved": "6.0.0-be.662",
"contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"MonoMod.Utils": "22.7.31.1"
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"Disarm": {
"type": "Transitive",
"resolved": "2022.1.0-master.57",
"contentHash": "/dkg7hg8iPBQN4bTV1lMQacarH6fMpgUXhJuo6iI7Wv7YpH7g5F9hJfje7dSMhqG0YlDacLuyWvcph5GzKUXog=="
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.2",
"contentHash": "/5WwkxXX8mPsRuigQt957rJGx1f0dDQxk+bvk4yYITKFjXas9Em+O71zEP8X0ym8OFQQ2XH/2SxS4NC7vEC+Xg==",
"resolved": "2.10.0",
"contentHash": "4ayiy/dlCiW86K2N7Jvbf+VpI5wvP7dncv/6oRmfwRi32UCmCRzCGzsxdMfzJZkp6/26oBW+DrD8vi4UejzVAg==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
@@ -128,13 +81,13 @@
},
"Iced": {
"type": "Transitive",
"resolved": "1.21.0",
"contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "pI0kU0qqJKMP6z9eFz4+WJtGIwklfPxW2yWEY9vKnrN9bbYMusK3v5uFWV8al7S/HPSATV5jNWH1hyTvP7kglA==",
"resolved": "1.3.0",
"contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
@@ -143,29 +96,61 @@
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "kecdx/vbNl0RtfzfYW592jU8PMyq1JbzpvoJSvqwO+tV6icp9SljXy6yG8bT/wt0gaPj9mFUNDTe2Wu6M6XGZQ==",
"resolved": "1.3.0",
"contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==",
"dependencies": {
"Il2CppInterop.Common": "1.4.6-ci.426",
"Il2CppInterop.Common": "1.3.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "rd2T5o6SybIc12hmX3HktTF5n27hFb0w4mNSExq7h1YsmrNlt7x+Ac1MBnnB0JwPLIg7w8LjnKjoIX6Gf626ng==",
"resolved": "1.3.0",
"contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.6-ci.426"
"Il2CppInterop.Runtime": "1.3.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "0O0oI7gOqJixrsjvh1firhuGYK3Yr0uDLp6Q+t5CfcTMmeEX8Plk3pqAP9ZYyilBvh7uW0gv4Golqz08L1GXug==",
"resolved": "1.3.0",
"contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.6-ci.426"
"Il2CppInterop.Common": "1.3.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Linguini.Bundle": {
"type": "Transitive",
"resolved": "0.3.1",
"contentHash": "k3D0IBSsS91T0G9rYACRYtAS27NDTGz4T3ygHhbhaFdA9i3cCfCpR39MqYEpoA1Ark3lzmvklHePmRCX5EQi1A==",
"dependencies": {
"Linguini.Shared": "0.3.0",
"Linguini.Syntax": "0.3.0"
}
},
"Linguini.Shared": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "rEYA9jWU1Nc9iDuPKar+4IVXjFbGrcNyYZCeU6hiWQoS4nA2UecHu36Rp4bxzasvRGda4FB2JZqty75m4e26VQ=="
},
"Linguini.Syntax": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "v8YV3xPFZfP+OSWjMd6yysp+o7cNnQXxq/slN8Yekoi+dFjsTNF0YiQWJIwg1j2FUbs6claJxY9R1FFlc4s6MA==",
"dependencies": {
"Linguini.Shared": "0.3.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
@@ -190,11 +175,11 @@
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nxVJTvQbWAujaogt5XX3eAy7d22t66Z88aWg9sirPLO9rR/6yNCHAyZpgxXrOsIobZVW0IEZPqNMOBhgke25/w==",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.7.31.1",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
@@ -205,8 +190,8 @@
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nI0E1oadXS1iMbfwfCzYF08C1jRQR9cnnHv66a4BSPd4sGu2p6g4BmctCWsdAB6oGKkSJUhcfHfxcfTsDyB94Q==",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
@@ -317,46 +302,42 @@
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "mAYIrMo0VdOZzh1NS5bZeflg80gtYNY7kZo9q/blEYheUPyLXu5ozQOjX+Bq2yDh40pA+yiE2MXTnN2Is2hjgw==",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1",
"AssetRipper.CIL": "1.1.2",
"AssetRipper.Gee.External.Capstone": "2.3.2",
"Disarm": "2022.1.0-master.57",
"Iced": "1.21.0",
"Samboy063.LibCpp2IL": "2022.1.0-pre-release.19",
"StableNameDotNet": "0.1.0-pre-release.19"
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "/n8p81ltd38BeNNS2xUNPGMSzxk/UGXr9cRNqG1MaLogzANNNrvCAXqWmNMM3tZctjp7vqTxEA+e4J4ngul8Fg==",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"Samboy063.WasmDisassembler": "2022.1.0-pre-release.19"
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "uVQdYm/J6+jJ1xt6GJ3hNhXhciwlX+LmHTPITu9jjZ75T33YJuuTD7pLVYuMymr+4gSVisg7f1wterFSyqJBWA=="
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StableNameDotNet": {
"type": "Transitive",
"resolved": "0.1.0-pre-release.19",
"contentHash": "5BPWtntv3PXeFIg9CuGW6OM3f5GnwvdQJbzRpufPsistFwFyt1xYW1wSDr+QIdDO7vLndr7iNpWD3FyYp9LL4g=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.556",
"contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ=="
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections": {
"type": "Transitive",
@@ -900,10 +881,16 @@
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"reactor": {
"type": "Project",
"dependencies": {
"BepInEx.Unity.IL2CPP": "[6.0.0-be.735, )"
"BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )",
"Linguini.Bundle": "[0.3.1, )"
}
}
}
-2
View File
@@ -25,8 +25,6 @@ public partial class ExamplePlugin : BasePlugin
public override void Load()
{
ReactorCredits.Register<ExamplePlugin>(ReactorCredits.AlwaysShow);
this.AddComponent<ExampleComponent>();
_helloStringName = CustomStringName.CreateAndRegister("Hello!");
+110 -123
View File
@@ -4,9 +4,9 @@
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2025.4.15, )",
"resolved": "2025.4.15",
"contentHash": "R3RxzHGZOGUJ9nMwrP0cjS6g+sh60QUU506Mo47lh17155enUjH6PtErijihSoU7t3aQpzCIyC67W3XrrHhH4g=="
"requested": "[2022.10.25, )",
"resolved": "2022.10.25",
"contentHash": "PWgkH/VvMlShVhZB8G432q0tnMaNVZrbIdbEMCZN/fETUlT/ch+qQj4PdTcZhPHREbnJHH3ijHxlca1d7QMBcQ=="
},
"BepInEx.AutoPlugin": {
"type": "Direct",
@@ -16,111 +16,64 @@
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.1.0-rc.1, )",
"resolved": "2.1.0-rc.1",
"contentHash": "WI/7TbJwWl5P4B6UXGtKI1VMe6fA6h3fcbp3ZjJKqOBQ5MJfDMmeVB4fb+RW1tUQdxnlSWV3Ul62PHFyTqp4PA=="
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.735, )",
"resolved": "6.0.0-be.735",
"contentHash": "2+eFJGKMR1GFPeU9wuF+TVrMANIaWIc/6N9e8x4b7b/fNiY9B6vicYNiMDb2deYQpWZtOei+2btnar5dDE5BPg==",
"requested": "[6.0.0-be.662, )",
"resolved": "6.0.0-be.662",
"contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.735",
"BepInEx.Unity.Common": "6.0.0-be.735",
"HarmonyX": "2.10.2",
"Iced": "1.21.0",
"Il2CppInterop.Generator": "1.4.6-ci.426",
"Il2CppInterop.HarmonySupport": "1.4.6-ci.426",
"Il2CppInterop.Runtime": "1.4.6-ci.426",
"MonoMod.RuntimeDetour": "22.7.31.1",
"Samboy063.Cpp2IL.Core": "2022.1.0-pre-release.19"
"BepInEx.Core": "6.0.0-be.662",
"BepInEx.Unity.Common": "6.0.0-be.662",
"HarmonyX": "2.10.0",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.3.0",
"Il2CppInterop.HarmonySupport": "1.3.0",
"Il2CppInterop.Runtime": "1.3.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.556, )",
"resolved": "1.2.0-beta.556",
"contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.556"
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AsmResolver": {
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "M5btCR/rmrx32jZsoN6CLQ/VQk8lN8hvPb6lgojua7pjNoo7StAl92koMC8qz4vzZyH2CNqxLSDoswRvyyK/vA=="
},
"AsmResolver.DotNet": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "PTq8nNQvhgTxF1iARCknffCsu7Iq9B0kN7TVC8iMaU7uEYog3xvVqH/0+TreY8GW74/+MqhZt/yEFsvS4oAduQ==",
"dependencies": {
"AsmResolver.PE": "6.0.0-beta.1"
}
},
"AsmResolver.PE": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "KadLvx/zzFCJyF+E4jG6jPE1d0iJquzL6+hm8GBivBAs6nwHC8s6g4c857QwQCzXMWza6Vz5Q+3hFiNuOfKaWQ==",
"dependencies": {
"AsmResolver.PE.File": "6.0.0-beta.1"
}
},
"AsmResolver.PE.File": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "+lusB9UMHevI5aQsu73NQ1ctPMLFvyHAsEf8vjaJ/py+kX1DkU0JkbERtBRmaf58/hBZ7cyrE7gFnjoo7Bbg7A==",
"dependencies": {
"AsmResolver": "6.0.0-beta.1"
}
},
"AssetRipper.CIL": {
"type": "Transitive",
"resolved": "1.1.2",
"contentHash": "BRPcHORadIzSFkrVOvGkSs54j19mQdXH8dmRTVM51mS8MZLSbTpi9CDPpnWN2IdDsILUrAqbPUFo3zJodYxErw==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1"
}
},
"AssetRipper.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "wOr5PQPL/2ZfD7+ebt6cpRbUhSzSY5nlHGHjjzuQRiU5zkQlqQNwWDLX0M3smrm5IkaDvONkmDjFMKTlZJmyuQ=="
},
"AssetRipper.Primitives": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "djZbN/+EXmI+Oia9Pm0LyjZVCPLf60TPSL5rGb7mBEYM5F4CN3nPFXvl2yA5LanPZoHS1Yq7PghGUmkP7Pv9RQ=="
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "FuHm9UCzjSKeiZJc3IF70Fiuqi+FynRn62PwBoOeZcHK3/qm+vl1YwbZyFlmUyf45g+UKxg2Td40iZGx88LVAQ==",
"resolved": "6.0.0-be.662",
"contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==",
"dependencies": {
"HarmonyX": "2.10.2",
"MonoMod.Utils": "22.7.31.1",
"HarmonyX": "2.10.0",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "vmK//OBSr+jotqTk//HSdvHtMFTKu+NlQkiEsvr0dZApTVmQM2AgpVMhEAakQPmrSsM6LRJIHCBcLFO1ypfMPQ==",
"resolved": "6.0.0-be.662",
"contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"MonoMod.Utils": "22.7.31.1"
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"Disarm": {
"type": "Transitive",
"resolved": "2022.1.0-master.57",
"contentHash": "/dkg7hg8iPBQN4bTV1lMQacarH6fMpgUXhJuo6iI7Wv7YpH7g5F9hJfje7dSMhqG0YlDacLuyWvcph5GzKUXog=="
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.2",
"contentHash": "/5WwkxXX8mPsRuigQt957rJGx1f0dDQxk+bvk4yYITKFjXas9Em+O71zEP8X0ym8OFQQ2XH/2SxS4NC7vEC+Xg==",
"resolved": "2.10.0",
"contentHash": "4ayiy/dlCiW86K2N7Jvbf+VpI5wvP7dncv/6oRmfwRi32UCmCRzCGzsxdMfzJZkp6/26oBW+DrD8vi4UejzVAg==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
@@ -128,13 +81,13 @@
},
"Iced": {
"type": "Transitive",
"resolved": "1.21.0",
"contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "pI0kU0qqJKMP6z9eFz4+WJtGIwklfPxW2yWEY9vKnrN9bbYMusK3v5uFWV8al7S/HPSATV5jNWH1hyTvP7kglA==",
"resolved": "1.3.0",
"contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
@@ -143,29 +96,61 @@
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "kecdx/vbNl0RtfzfYW592jU8PMyq1JbzpvoJSvqwO+tV6icp9SljXy6yG8bT/wt0gaPj9mFUNDTe2Wu6M6XGZQ==",
"resolved": "1.3.0",
"contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==",
"dependencies": {
"Il2CppInterop.Common": "1.4.6-ci.426",
"Il2CppInterop.Common": "1.3.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "rd2T5o6SybIc12hmX3HktTF5n27hFb0w4mNSExq7h1YsmrNlt7x+Ac1MBnnB0JwPLIg7w8LjnKjoIX6Gf626ng==",
"resolved": "1.3.0",
"contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.6-ci.426"
"Il2CppInterop.Runtime": "1.3.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "0O0oI7gOqJixrsjvh1firhuGYK3Yr0uDLp6Q+t5CfcTMmeEX8Plk3pqAP9ZYyilBvh7uW0gv4Golqz08L1GXug==",
"resolved": "1.3.0",
"contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.6-ci.426"
"Il2CppInterop.Common": "1.3.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Linguini.Bundle": {
"type": "Transitive",
"resolved": "0.3.1",
"contentHash": "k3D0IBSsS91T0G9rYACRYtAS27NDTGz4T3ygHhbhaFdA9i3cCfCpR39MqYEpoA1Ark3lzmvklHePmRCX5EQi1A==",
"dependencies": {
"Linguini.Shared": "0.3.0",
"Linguini.Syntax": "0.3.0"
}
},
"Linguini.Shared": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "rEYA9jWU1Nc9iDuPKar+4IVXjFbGrcNyYZCeU6hiWQoS4nA2UecHu36Rp4bxzasvRGda4FB2JZqty75m4e26VQ=="
},
"Linguini.Syntax": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "v8YV3xPFZfP+OSWjMd6yysp+o7cNnQXxq/slN8Yekoi+dFjsTNF0YiQWJIwg1j2FUbs6claJxY9R1FFlc4s6MA==",
"dependencies": {
"Linguini.Shared": "0.3.0"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
@@ -190,11 +175,11 @@
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nxVJTvQbWAujaogt5XX3eAy7d22t66Z88aWg9sirPLO9rR/6yNCHAyZpgxXrOsIobZVW0IEZPqNMOBhgke25/w==",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.7.31.1",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
@@ -205,8 +190,8 @@
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nI0E1oadXS1iMbfwfCzYF08C1jRQR9cnnHv66a4BSPd4sGu2p6g4BmctCWsdAB6oGKkSJUhcfHfxcfTsDyB94Q==",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
@@ -317,46 +302,42 @@
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "mAYIrMo0VdOZzh1NS5bZeflg80gtYNY7kZo9q/blEYheUPyLXu5ozQOjX+Bq2yDh40pA+yiE2MXTnN2Is2hjgw==",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1",
"AssetRipper.CIL": "1.1.2",
"AssetRipper.Gee.External.Capstone": "2.3.2",
"Disarm": "2022.1.0-master.57",
"Iced": "1.21.0",
"Samboy063.LibCpp2IL": "2022.1.0-pre-release.19",
"StableNameDotNet": "0.1.0-pre-release.19"
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "/n8p81ltd38BeNNS2xUNPGMSzxk/UGXr9cRNqG1MaLogzANNNrvCAXqWmNMM3tZctjp7vqTxEA+e4J4ngul8Fg==",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"Samboy063.WasmDisassembler": "2022.1.0-pre-release.19"
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "uVQdYm/J6+jJ1xt6GJ3hNhXhciwlX+LmHTPITu9jjZ75T33YJuuTD7pLVYuMymr+4gSVisg7f1wterFSyqJBWA=="
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StableNameDotNet": {
"type": "Transitive",
"resolved": "0.1.0-pre-release.19",
"contentHash": "5BPWtntv3PXeFIg9CuGW6OM3f5GnwvdQJbzRpufPsistFwFyt1xYW1wSDr+QIdDO7vLndr7iNpWD3FyYp9LL4g=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.556",
"contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ=="
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections": {
"type": "Transitive",
@@ -900,10 +881,16 @@
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
},
"reactor": {
"type": "Project",
"dependencies": {
"BepInEx.Unity.IL2CPP": "[6.0.0-be.735, )"
"BepInEx.Unity.IL2CPP": "[6.0.0-be.662, )",
"Linguini.Bundle": "[0.3.1, )"
}
}
}
@@ -0,0 +1,36 @@
using System.Text;
using System.Text.RegularExpressions;
using Linguini.Syntax.Ast;
namespace Reactor.Linguinitor;
internal static class FluentCommentParser
{
private static readonly Regex _variableCommentRegex = new(@"^\$(?<id>[\w-]+) \((?<type>String|Number|Date)\)( - (?<description>.+))?$", RegexOptions.Compiled);
public static MessageInfo Parse(AstComment astComment)
{
var descriptionBuilder = new StringBuilder();
var variables = new Dictionary<string, VariableInfo>();
foreach (var s in astComment.AsStr().Split("\n"))
{
var line = s.Trim();
if (_variableCommentRegex.Match(line) is { Success: true } match)
{
variables.Add(match.Groups["id"].Value, new VariableInfo(match.Groups["type"].Value, match.Groups["description"].Value));
}
else
{
descriptionBuilder.AppendLine(line);
}
}
return new MessageInfo(descriptionBuilder.ToString(), variables);
}
public record MessageInfo(string Description, Dictionary<string, VariableInfo> Variables);
public record VariableInfo(string Type, string? Description);
}
+166
View File
@@ -0,0 +1,166 @@
using CSharpPoet;
using Linguini.Syntax.Ast;
using Linguini.Syntax.Parser;
using Microsoft.CodeAnalysis;
namespace Reactor.Linguinitor;
[Generator(LanguageNames.CSharp)]
public class LinguinitorGenerator : IIncrementalGenerator
{
private static CSharpFile CreateTranslateFile(string @namespace, params CSharpType.IMember[] members)
{
return new CSharpFile(@namespace)
{
new CSharpClass(Visibility.Internal, "Translate")
{
IsStatic = true,
IsPartial = true,
Members = members,
},
};
}
private static IEnumerable<Identifier> GetVariables(AstMessage astMessage)
{
foreach (var placeable in astMessage.Value!.Elements.OfType<Placeable>())
{
switch (placeable.Expression)
{
case VariableReference variableReference:
yield return variableReference.Id;
break;
}
}
}
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var rootNamespaceProvider =
context.AnalyzerConfigOptionsProvider
.Select((options, _) => options.GlobalOptions.TryGetValue("build_property.RootNamespace", out var rootNamespace) ? rootNamespace : throw new InvalidOperationException("Failed to get RootNamespace"));
context.RegisterSourceOutput(rootNamespaceProvider, (spc, rootNamespace) =>
{
const string ProviderType = "Reactor.Localization.Providers.FluentLocalizationProvider";
spc.AddSource("Translate", CreateTranslateFile(
rootNamespace,
new CSharpField(Visibility.Private, ProviderType + "?", "_provider") { IsStatic = true },
new CSharpProperty(ProviderType, "Provider")
{
IsStatic = true,
Getter = new CSharpProperty.Accessor
{
Body = writer => writer.Write("_provider ?? throw new System.InvalidOperationException(\"Provider must be set before using Translate\");"),
},
Setter = new CSharpProperty.Accessor
{
Body = writer => writer.Write("_provider = value;"),
},
}
).ToString());
});
var textFiles = context.AdditionalTextsProvider.Where(static file => file.Path.EndsWith(".ftl", StringComparison.Ordinal));
var namesAndContents = textFiles.Select((text, cancellationToken) => (
Name: Path.GetFileNameWithoutExtension(text.Path),
Content: text.GetText(cancellationToken)!.ToString()
));
context.RegisterSourceOutput(namesAndContents.Combine(rootNamespaceProvider), (spc, pair) =>
{
var ((name, content), rootNamespace) = pair;
var fixedName = name.ToPascalCase();
var idsClass = new CSharpClass("Ids")
{
IsStatic = true,
};
var fileClass = new CSharpClass(fixedName)
{
IsStatic = true,
Members = { idsClass },
};
var resource = new LinguiniParser(content).ParseWithComments();
foreach (var message in resource.Entries.OfType<AstMessage>())
{
var id = message.GetId();
var fixedId = id.ToPascalCase();
idsClass.Members.Add(new CSharpField(Visibility.Public, "string", fixedId)
{
IsConst = true,
DefaultValue = $"\"{id}\"",
});
var messageInfo = message.Comment != null ? FluentCommentParser.Parse(message.Comment) : null;
var variables = GetVariables(message).Select(m => m.ToString()).ToDictionary(
m => m,
m =>
{
if (messageInfo != null && messageInfo.Variables.TryGetValue(m, out var variableInfo))
{
return variableInfo.Type switch
{
"String" => "string",
"Number" => "double",
_ => throw new NotSupportedException($"Variable type {variableInfo.Type} is not supported"),
};
}
return "string";
}
);
void WriteComment(CodeWriter writer)
{
if (messageInfo == null) return;
writer.WriteLine("<summary>");
foreach (var line in messageInfo.Description.Trim().Split("\n"))
{
writer.WriteLine(line);
}
writer.WriteLine("</summary>");
foreach (var (variableId, info) in messageInfo.Variables)
{
writer.WriteLine($"<param name=\"{variableId}\">{info.Description}</param>");
}
}
if (variables.Count <= 0)
{
fileClass.Members.Add(new CSharpProperty("string", fixedId)
{
XmlComment = WriteComment,
IsStatic = true,
Getter = new CSharpProperty.Accessor
{
Body = writer => writer.Write($"Provider.GetText(Ids.{fixedId});"),
},
});
}
else
{
fileClass.Members.Add(new CSharpMethod("string", fixedId)
{
XmlComment = WriteComment,
IsStatic = true,
Parameters = variables.Select(v => new CSharpParameter(v.Value, v.Key)).ToArray(),
BodyType = BodyType.Expression,
Body = writer => writer.WriteLine($"Provider.GetText(Ids.{fixedId}, {string.Join(", ", variables.Select(v => $"(\"{v.Key}\", {v.Key.ToCamelCase()})"))});"),
});
}
}
spc.AddSource("Translate." + fixedName, CreateTranslateFile(rootNamespace, fileClass).ToString());
});
}
}
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net472</TargetFrameworks>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CSharpPoet" Version="0.2.0-dev" Private="true" GeneratePathProperty="true" />
<PackageReference Include="Linguini.Shared" Version="0.3.0" Private="true" GeneratePathProperty="true" />
<PackageReference Include="Linguini.Syntax" Version="0.3.0" Private="true" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
</PropertyGroup>
<Target Name="GetDependencyTargetPaths">
<PropertyGroup>
<_LinguiniTargetFramework Condition="'$(TargetFramework)' == 'net6.0'">netstandard2.1</_LinguiniTargetFramework>
<_LinguiniTargetFramework Condition="'$(TargetFramework)' == 'net472'">net451</_LinguiniTargetFramework>
</PropertyGroup>
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PkgCSharpPoet)\lib\netstandard2.0\CSharpPoet.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PkgLinguini_Shared)\lib\$(_LinguiniTargetFramework)\Linguini.Shared.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PkgLinguini_Syntax)\lib\$(_LinguiniTargetFramework)\Linguini.Syntax.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>
</Project>
+38
View File
@@ -0,0 +1,38 @@
using System.Text;
namespace Reactor.Linguinitor;
internal static class StringExtensions
{
private static string ToCase(this string value, bool capitalizeFirst)
{
var stringBuilder = new StringBuilder();
for (var i = 0; i < value.Length; i++)
{
var c = value[i];
if (c == '-')
{
i++;
stringBuilder.Append(char.ToUpperInvariant(value[i]));
}
else
{
stringBuilder.Append(capitalizeFirst && i == 0 ? char.ToUpperInvariant(c) : c);
}
}
return stringBuilder.ToString();
}
public static string ToPascalCase(this string value)
{
return value.ToCase(true);
}
public static string ToCamelCase(this string value)
{
return value.ToCase(false);
}
}
+105
View File
@@ -0,0 +1,105 @@
{
"version": 1,
"dependencies": {
"net6.0": {
"CSharpPoet": {
"type": "Direct",
"requested": "[0.2.0-dev, )",
"resolved": "0.2.0-dev"
},
"Linguini.Shared": {
"type": "Direct",
"requested": "[0.3.0, )",
"resolved": "0.3.0",
"contentHash": "rEYA9jWU1Nc9iDuPKar+4IVXjFbGrcNyYZCeU6hiWQoS4nA2UecHu36Rp4bxzasvRGda4FB2JZqty75m4e26VQ=="
},
"Linguini.Syntax": {
"type": "Direct",
"requested": "[0.3.0, )",
"resolved": "0.3.0",
"contentHash": "v8YV3xPFZfP+OSWjMd6yysp+o7cNnQXxq/slN8Yekoi+dFjsTNF0YiQWJIwg1j2FUbs6claJxY9R1FFlc4s6MA==",
"dependencies": {
"Linguini.Shared": "0.3.0"
}
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Direct",
"requested": "[4.3.1, )",
"resolved": "4.3.1",
"contentHash": "5C9VHvahL98tumlyaT/loB5rW+K/6q0UU7uLyT1Dv15YjZraRkqML9u2t2e8GaO7XqEOtBVqK/SlxXOPqwzxog==",
"dependencies": {
"Microsoft.CodeAnalysis.Common": "[4.3.1]"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"Microsoft.CodeAnalysis.Analyzers": {
"type": "Transitive",
"resolved": "3.3.3",
"contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ=="
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "4.3.1",
"contentHash": "wexpJffSEEwptwe6UTMxRDZCCtz+XubI4Qewl4JECnNhcQrtb0anhSUEV9Nz7WkoNfWkx1fptR8xh1egoxYrqw==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "3.3.3",
"System.Collections.Immutable": "6.0.0",
"System.Memory": "4.5.4",
"System.Reflection.Metadata": "5.0.0",
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encoding.CodePages": "6.0.0",
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections.Immutable": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Memory": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw=="
},
"System.Reflection.Metadata": {
"type": "Transitive",
"resolved": "5.0.0",
"contentHash": "5NecZgXktdGg34rh1OenY1rFNDCI8xSjFr+Z4OU4cU06AQHUdRnIIEeWENu3Wl4YowbzkymAIMvi3WyK9U53pQ=="
},
"System.Runtime.CompilerServices.Unsafe": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
},
"System.Text.Encoding.CodePages": {
"type": "Transitive",
"resolved": "6.0.0",
"contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Threading.Tasks.Extensions": {
"type": "Transitive",
"resolved": "4.5.4",
"contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg=="
}
}
}
}
+3 -3
View File
@@ -94,18 +94,18 @@ public readonly struct Mod : IEquatable<Mod>
var clientMissing = hostMods.Where(mod => mod.IsRequiredOnAllClients && !clientMods.Contains(mod)).ToArray();
var hostMissing = clientMods.Where(mod => mod.IsRequiredOnAllClients && !hostMods.Contains(mod)).ToArray();
if (clientMissing.Length != 0 || hostMissing.Length != 0)
if (clientMissing.Any() || hostMissing.Any())
{
var message = new StringBuilder();
if (clientMissing.Length != 0)
if (clientMissing.Any())
{
message.Append("You are missing: ");
message.AppendJoin(", ", clientMissing.Select(x => x.ToString()));
message.AppendLine();
}
if (hostMissing.Length != 0)
if (hostMissing.Any())
{
message.Append("Host is missing: ");
message.AppendJoin(", ", hostMissing.Select(x => x.ToString()));
-5
View File
@@ -27,9 +27,4 @@ public enum ModFlags : ushort
/// Requires the host of the lobby to have the mod.
/// </summary>
RequireOnHost = 1 << 2,
/// <summary>
/// Notifies the game server that the host has authority over game logic.
/// </summary>
DisableServerAuthority = 1 << 3,
}
+6
View File
@@ -18,6 +18,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Networking.Shared", "Reactor.Networking.Shared\Reactor.Networking.Shared.csproj", "{1E68CA20-22EB-4E57-B525-81970BE6363D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reactor.Linguinitor", "Reactor.Linguinitor\Reactor.Linguinitor.csproj", "{B4740F75-B657-4515-A8F6-8A84D64E8814}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -44,6 +46,10 @@ Global
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E68CA20-22EB-4E57-B525-81970BE6363D}.Release|Any CPU.Build.0 = Release|Any CPU
{B4740F75-B657-4515-A8F6-8A84D64E8814}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B4740F75-B657-4515-A8F6-8A84D64E8814}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B4740F75-B657-4515-A8F6-8A84D64E8814}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B4740F75-B657-4515-A8F6-8A84D64E8814}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
@@ -0,0 +1,10 @@
-for-more-info-see = For more info see https://reactor.gg/handshake
vanilla-server-warning =
This server doesn't support Reactor protocol.
The lobbies shown may not be compatible with your current mods.
{ -for-more-info-see }
public-lobby-warning =
You can't make public lobbies on servers that don't support Reactor protocol.
{ -for-more-info-see }
@@ -0,0 +1,10 @@
-for-more-info-see = Voor meer informatie, zie https://reactor.gg/handshake
vanilla-server-warning =
Deze server ondersteunt het Reactor protocol niet.
De lobbies die je ziet passen mogelijk niet bij jouw huidige mods.
{ -for-more-info-see }
public-lobby-warning =
Je kan geen publieke lobbies maken op servers die het Reactor protocol niet ondersteunen.
{ -for-more-info-see }
@@ -0,0 +1,10 @@
-for-more-info-see = Dla więcej informacji, zobacz https://reactor.gg/handshake
vanilla-server-warning =
Ten serwer nie wspiera protokołu Reactor.
Pokazane gry mogą nie być kompatibline z twoimi modami.
{ -for-more-info-see }
public-lobby-warning =
Nie możesz tworzyć publicznych gier w serwerach, które nie wspierają protokołu Reactor.
{ -for-more-info-see }
Binary file not shown.
Binary file not shown.
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
global using AmongUsClient_CoFindGame = AmongUsClient._CoFindGame_d__54;
@@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Linguini.Bundle;
using Linguini.Bundle.Builder;
using Linguini.Bundle.Errors;
using Linguini.Shared.Types.Bundle;
using Linguini.Syntax.Ast;
using Reactor.Localization.Extensions;
using Reactor.Localization.Utilities;
using Reactor.Utilities;
using Object = Il2CppSystem.Object;
namespace Reactor.Localization.Providers;
/// <summary>
/// Represents a localization provider that uses Fluent.
/// </summary>
public class FluentLocalizationProvider : LocalizationProvider
{
private readonly Func<CultureInfo, IEnumerable<Resource>> _loadResources;
private readonly List<FluentBundle> _bundles = new();
private readonly Dictionary<StringNames, string> _ids = new();
private readonly Dictionary<StringNames, string[]> _arguments = new();
/// <summary>
/// Gets or sets the fallback language.
/// </summary>
public SupportedLangs FallbackLanguage { get; set; } = SupportedLangs.English;
/// <summary>
/// Initializes a new instance of the <see cref="FluentLocalizationProvider"/> class.
/// </summary>
/// <param name="loadResources">The implementation of resource loading.</param>
public FluentLocalizationProvider(Func<CultureInfo, IEnumerable<Resource>> loadResources)
{
_loadResources = loadResources;
}
/// <summary>
/// Initializes a new instance of the <see cref="FluentLocalizationProvider"/> class that loads resources from the calling assembly.
/// </summary>
/// <param name="prefix">The prefix of resource file names to load.</param>
/// <returns>a <see cref="FluentLocalizationProvider"/>.</returns>
public static FluentLocalizationProvider FromEmbeddedResources(string prefix) => FromEmbeddedResources(Assembly.GetCallingAssembly(), prefix);
/// <summary>
/// Initializes a new instance of the <see cref="FluentLocalizationProvider"/> class that loads resources from the specified <paramref name="assembly"/>.
/// </summary>
/// <param name="assembly">The assembly to load resources from.</param>
/// <param name="prefix">The prefix of resource file names to load.</param>
/// <returns>a <see cref="FluentLocalizationProvider"/>.</returns>
public static FluentLocalizationProvider FromEmbeddedResources(Assembly assembly, string prefix)
{
return new FluentLocalizationProvider(cultureInfo =>
{
return assembly.GetManifestResourceNames()
.Where(n => n.StartsWith($"{prefix}.{cultureInfo.Name}.", StringComparison.Ordinal) && n.EndsWith(".ftl", StringComparison.Ordinal))
.Select(n => (Resource) new StreamReader(assembly.GetManifestResourceStream(n)!));
});
}
/// <summary>
/// Registers a <see cref="StringNames"/> for use with base game apis.
/// </summary>
/// <param name="id">The id of a Fluent message.</param>
/// <returns>A <see cref="StringNames"/>.</returns>
public StringNames Register(string id)
{
var stringNames = CustomStringName.Create();
_ids[stringNames] = id;
return stringNames;
}
/// <summary>
/// Registers a <see cref="StringNames"/> for use with base game apis with overriden format argument names.
/// </summary>
/// <param name="id">The id of a Fluent message.</param>
/// <param name="argumentNames">An array of Fluent variable names in the same order as format arguments.</param>
/// <returns>A <see cref="StringNames"/>.</returns>
public StringNames Register(string id, params string[] argumentNames)
{
var stringNames = Register(id);
_arguments[stringNames] = argumentNames;
return stringNames;
}
/// <inheritdoc/>
public override int Priority => ReactorPriority.Normal;
/// <inheritdoc />
public override void OnLanguageChanged(SupportedLangs newLanguage)
{
if (CurrentLanguage == newLanguage) return;
_bundles.Clear();
_bundles.Add(Load(newLanguage.ToCultureInfo()));
if (newLanguage != FallbackLanguage) _bundles.Add(Load(FallbackLanguage.ToCultureInfo()));
}
private FluentBundle Load(CultureInfo culture)
{
return LinguiniBuilder.Builder()
.CultureInfo(culture)
.AddResources(_loadResources(culture))
.SetUseIsolating(false)
.UncheckedBuild();
}
private string GetMsg(string id, IDictionary<string, IFluentType>? args)
{
foreach (var bundle in _bundles)
{
if (bundle.TryGetMsg(id, null, args, out var errors, out var message))
{
if (errors.Count > 0)
{
throw new LinguiniException(errors);
}
return message;
}
}
throw new KeyNotFoundException();
}
private static bool Is<T>(Il2CppObjectBase o)
{
return IL2CPP.il2cpp_class_is_assignable_from(Il2CppClassPointerStore<T>.NativeClassPtr, IL2CPP.il2cpp_object_get_class(o.Pointer));
}
private static bool TryUnbox<T>(Il2CppObjectBase o, [NotNullWhen(true)] out T? result) where T : unmanaged
{
if (!Is<T>(o))
{
result = null;
return false;
}
result = o.Unbox<T>();
return true;
}
private static IFluentType ToFluentType(Object o)
{
if (Is<string>(o)) return new FluentString(IL2CPP.Il2CppStringToManaged(o.Pointer));
if (TryUnbox<byte>(o, out var @byte)) return (FluentNumber) @byte;
if (TryUnbox<sbyte>(o, out var @sbyte)) return (FluentNumber) @sbyte;
if (TryUnbox<short>(o, out var @short)) return (FluentNumber) @short;
if (TryUnbox<int>(o, out var @int)) return (FluentNumber) @int;
if (TryUnbox<long>(o, out var @long)) return (FluentNumber) @long;
if (TryUnbox<ushort>(o, out var @ushort)) return (FluentNumber) @ushort;
if (TryUnbox<uint>(o, out var @uint)) return (FluentNumber) @uint;
if (TryUnbox<ulong>(o, out var @ulong)) return (FluentNumber) @ulong;
if (TryUnbox<float>(o, out var @float)) return (FluentNumber) @float;
if (TryUnbox<double>(o, out var @double)) return (FluentNumber) @double;
return new FluentString(o.ToString());
}
private static IFluentType ToFluentType(object o)
{
return o switch
{
string str => (FluentString) str,
byte num => (FluentNumber) num,
sbyte num => (FluentNumber) num,
short num => (FluentNumber) num,
ushort num => (FluentNumber) num,
int num => (FluentNumber) num,
uint num => (FluentNumber) num,
long num => (FluentNumber) num,
ulong num => (FluentNumber) num,
double num => (FluentNumber) num,
float num => (FluentNumber) num,
_ => (FluentString) o.ToString()!,
};
}
/// <summary>
/// Returns the localized text for the given fluent message <paramref name="id"/>.
/// </summary>
/// <param name="id">The id of the message.</param>
/// <param name="args">The arguments used for formatting.</param>
/// <returns>Text localized and formatted by fluent.</returns>
public string GetText(string id, params (string, object)[] args)
{
var fluentArgs = new Dictionary<string, IFluentType>(args.Length);
foreach (var (key, value) in args)
{
fluentArgs[key] = ToFluentType(value);
}
return GetMsg(id, fluentArgs);
}
/// <inheritdoc/>
public override bool TryGetTextFormatted(StringNames stringName, Il2CppReferenceArray<Object> parts, [NotNullWhen(true)] out string? result)
{
if (_ids.TryGetValue(stringName, out var id))
{
var hasArgumentsOverride = _arguments.TryGetValue(stringName, out var arguments);
if (hasArgumentsOverride)
{
if (arguments!.Length != parts.Length)
throw new InvalidOperationException($"Arguments override for {id} has an invalid count of arguments");
}
var args = new Dictionary<string, IFluentType>(parts.Length);
for (var i = 0; i < parts.Count; i++)
{
var part = parts[i];
if (hasArgumentsOverride)
{
args[arguments![i]] = ToFluentType(part);
}
else
{
// Fluent doesn't allow positional variables nor starting variable names with numbers so we have to use a,b,c,d... instead
if (i > 25) throw new InvalidOperationException("Too many format parts");
var c = (char) ('a' + i);
args[c.ToString()] = ToFluentType(part);
}
}
result = GetMsg(id, args);
return true;
}
result = null;
return false;
}
/// <inheritdoc/>
public override bool TryGetText(StringNames stringName, [NotNullWhen(true)] out string? result)
{
if (_ids.TryGetValue(stringName, out var id))
{
result = GetMsg(id, null);
return true;
}
result = null;
return false;
}
}
@@ -38,7 +38,8 @@ public sealed class MessageConverterAttribute : Attribute
try
{
MessageSerializer.Register(type);
var messageConverter = (UnsafeMessageConverter) Activator.CreateInstance(type)!;
MessageSerializer.Register(messageConverter);
}
catch (Exception e)
{
@@ -51,6 +52,5 @@ public sealed class MessageConverterAttribute : Attribute
internal static void Initialize()
{
IL2CPPChainloader.Instance.PluginLoad += (_, assembly, _) => Register(assembly);
IL2CPPChainloader.Instance.Finished += MessageSerializer.ClearMaps;
}
}
@@ -36,8 +36,7 @@ public sealed class MethodRpcAttribute : Attribute
/// <summary>
/// Gets or sets a value indicating whether the rpc should be sent immediately.
/// </summary>
[Obsolete("Non-immediate RPCs were removed in 2025.5.20. All RPCs are immediate. This property will be removed in a future version.")]
public bool SendImmediately { get; set; } = true;
public bool SendImmediately { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MethodRpcAttribute"/> class.
@@ -72,7 +71,7 @@ public sealed class MethodRpcAttribute : Attribute
try
{
var customRpc = new MethodRpc(plugin, method, attribute.Id, attribute.SendOption, attribute.LocalHandling);
var customRpc = new MethodRpc(plugin, method, attribute.Id, attribute.SendOption, attribute.LocalHandling, attribute.SendImmediately);
PluginSingleton<ReactorPlugin>.Instance.CustomRpcManager.Register(customRpc);
}
catch (Exception e)
@@ -1,8 +1,6 @@
using System;
using System.Globalization;
using Hazel;
using Hazel.Udp;
using Reactor.Networking.Serialization;
using UnityEngine;
namespace Reactor.Networking.Extensions;
@@ -14,11 +12,10 @@ public static class ExtraMessageExtensions
{
private const float MIN = -50f;
private const float MAX = 50f;
private const float DIFF = MAX - MIN;
private static float ReverseLerp(float t)
{
return Mathf.Clamp01((t - MIN) / DIFF);
return Mathf.Clamp((t - MIN) / (MAX - MIN), 0f, 1f);
}
/// <summary>
@@ -35,33 +32,6 @@ public static class ExtraMessageExtensions
writer.Write(y);
}
/// <summary>
/// Writes an Enum value to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="value">The <see cref="Enum"/> to write.</param>
public static void Write(this MessageWriter writer, Enum value) => writer.Serialize(Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture));
/// <summary>
/// Writes a long value to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="value">The <see cref="long"/> to write.</param>
public static void Write(this MessageWriter writer, long value) => writer.Write(BitConverter.GetBytes(value));
/// <summary>
/// Writes a color value to the <paramref name="writer"/>.
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="value">The <see cref="Color32"/> to write.</param>
public static void Write(this MessageWriter writer, Color32 value)
{
writer.Write(value.r);
writer.Write(value.g);
writer.Write(value.b);
writer.Write(value.a);
}
/// <summary>
/// Reads a <see cref="Vector2"/> from the <paramref name="reader"/>.
/// </summary>
@@ -75,43 +45,6 @@ public static class ExtraMessageExtensions
return new Vector2(Mathf.Lerp(MIN, MAX, x), Mathf.Lerp(MIN, MAX, y));
}
/// <summary>
/// Reads an enum value and casts it to the specified type from a network message.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <typeparam name="T">The <see cref="Enum"/> type to convert to.</typeparam>
/// <returns>An <see cref="Enum"/> value from the <paramref name="reader"/>.</returns>
public static T ReadEnum<T>(this MessageReader reader) where T : struct, Enum => (T) reader.ReadEnum(typeof(T));
/// <summary>
/// Reads an enum value from a network message.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <param name="enumType">The type of the enum.</param>
/// <returns>The resulting enum value from the <paramref name="reader"/>.</returns>
public static object ReadEnum(this MessageReader reader, Type enumType) => Enum.ToObject(enumType, reader.Deserialize(Enum.GetUnderlyingType(enumType)));
/// <summary>
/// Reads a long value from a network message.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <returns>The resulting long value from the <paramref name="reader"/>.</returns>
public static long ReadInt64(this MessageReader reader) => BitConverter.ToInt64(reader.ReadBytes(8), 0);
/// <summary>
/// Reads a color value from a network message.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <returns>The resulting Color32 value from the <paramref name="reader"/>.</returns>
public static Color32 ReadColor32(this MessageReader reader) => new(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
/// <summary>
/// Reads a color value from a network message.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <returns>The resulting Color value from the <paramref name="reader"/>.</returns>
public static Color ReadColor(this MessageReader reader) => new(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
/// <summary>
/// Sends a message on the <paramref name="connection"/> with an <paramref name="ackCallback"/>.
/// </summary>
-35
View File
@@ -1,35 +0,0 @@
using Reactor.Utilities.UI;
using UnityEngine;
namespace Reactor.Networking;
internal static class HandshakePopup
{
public const string Message =
"""
This server doesn't support Reactor's modded handshake.
The lobbies shown could be incompatible with your current mods.
For more info see <link=https://reactor.gg/handshake>reactor.gg/handshake</link>
""";
private static ReactorPopup? _popup;
public static void Show()
{
if (_popup == null)
{
_popup = ReactorPopup.Create(nameof(HandshakePopup));
_popup.Background.transform.localPosition = new Vector3(0, 0.20f, 0);
_popup.Background.size = new Vector2(6.5f, 1.7f);
_popup.BackButton.transform.SetLocalY(-0.2f);
}
var message = ReactorConfig.HandshakePopupMessage.Value;
if (string.IsNullOrEmpty(message))
{
message = Message;
}
_popup.Show(message);
}
}
@@ -1,34 +0,0 @@
using Reactor.Utilities.UI;
using UnityEngine;
namespace Reactor.Networking;
internal static class MakePublicDisallowedPopup
{
public const string Message =
"""
You can't make public lobbies on servers that don't support modded handshake.
For more info see <link=https://reactor.gg/handshake>reactor.gg/handshake</link>
""";
private static ReactorPopup? _popup;
public static void Show()
{
if (_popup == null)
{
_popup = ReactorPopup.Create(nameof(MakePublicDisallowedPopup));
_popup.Background.transform.localPosition = new Vector3(0, 0.25f, 0);
_popup.Background.size = new Vector2(7.5f, 1.5f);
_popup.BackButton.transform.SetLocalY(-0.1f);
}
var message = ReactorConfig.MakePublicDisallowedPopupMessage.Value;
if (string.IsNullOrEmpty(message))
{
message = Message;
}
_popup.Show(message);
}
}
+1 -7
View File
@@ -39,9 +39,6 @@ public static class ModList
return _modByPluginType[pluginType];
}
internal static bool IsAnyModRequiredOnAllClients { get; private set; }
internal static bool IsAnyModDisableServerAuthority { get; private set; }
private static readonly Dictionary<uint, Mod> _modByNetId = new();
private static readonly Dictionary<Mod, uint> _netIdByMod = new();
@@ -101,7 +98,7 @@ public static class ModList
.Select(pluginInfo => GetById(pluginInfo.Metadata.GUID))
.OrderByDescending(x => x.Id == ReactorPlugin.Id)
.ThenBy(x => x.Id, StringComparer.Ordinal)
.ToArray();
.ToHashSet();
_modByNetId.Clear();
_netIdByMod.Clear();
@@ -116,9 +113,6 @@ public static class ModList
netId++;
}
IsAnyModRequiredOnAllClients = Current.Any(m => m.IsRequiredOnAllClients);
IsAnyModDisableServerAuthority = Current.Any(m => (m.Flags & ModFlags.DisableServerAuthority) != 0);
var debug = new StringBuilder("Mod list:");
foreach (var mod in Current)
{
+53 -84
View File
@@ -1,8 +1,4 @@
using System;
using System.Linq;
using AmongUs.Data;
using AmongUs.InnerNet.GameDataMessages;
using BepInEx.Unity.IL2CPP.Utils;
using HarmonyLib;
using Hazel;
using Il2CppInterop.Runtime;
@@ -11,7 +7,6 @@ using InnerNet;
using Reactor.Networking.Extensions;
using Reactor.Networking.Messages;
using UnityEngine;
using IEnumerator = System.Collections.IEnumerator;
namespace Reactor.Networking.Patches;
@@ -30,10 +25,10 @@ internal static class ClientPatches
}
}
[HarmonyPatch(typeof(InnerNetClient._HandleGameDataInner_d__165), nameof(InnerNetClient._HandleGameDataInner_d__165.MoveNext))]
[HarmonyPatch(typeof(InnerNetClient._HandleGameDataInner_d__39), nameof(InnerNetClient._HandleGameDataInner_d__39.MoveNext))]
public static class HandleGameDataInnerPatch
{
public static bool Prefix(InnerNetClient._HandleGameDataInner_d__165 __instance, ref bool __result)
public static bool Prefix(InnerNetClient._HandleGameDataInner_d__39 __instance, ref bool __result)
{
var innerNetClient = __instance.__4__this;
var reader = __instance.reader;
@@ -64,7 +59,7 @@ internal static class ClientPatches
return false;
}
if (reader.Tag == (byte) GameDataTypes.SceneChangeFlag && ReactorConnection.Instance?.Syncer == Syncer.Host)
if (ReactorConnection.Instance!.Syncer == Syncer.Host && reader.Tag == InnerNetClient.SceneChangeFlag)
{
var clientId = reader.ReadPackedInt32();
var clientData = innerNetClient.FindClientById(clientId);
@@ -88,56 +83,17 @@ internal static class ClientPatches
if (innerNetClient.AmHost)
{
if (reactorClientData == null && ModList.IsAnyModRequiredOnAllClients)
if (reactorClientData == null)
{
IEnumerator CoKick()
{
var startTime = DateTimeOffset.UtcNow;
string? playerName;
Warning("Kicking " + clientData.PlayerName + " for not having Reactor installed");
PlayerControl.LocalPlayer.RpcSendChat(clientData.PlayerName + " tried joining without Reactor installed");
innerNetClient.KickPlayer(clientData.Id, false);
do
{
yield return null;
if (DateTimeOffset.UtcNow - startTime > TimeSpan.FromSeconds(2))
{
playerName = "(unknown)";
break;
}
playerName = GameData.Instance.GetPlayerByClient(clientData)?.PlayerName;
} while (string.IsNullOrEmpty(playerName));
Warning("Kicking " + playerName + " for not having Reactor installed");
const int ChatMessageLimit = 100;
var chatText = $"{playerName} tried joining without the following mods:";
foreach (var mod in ModList.Current.Where(m => m.IsRequiredOnAllClients))
{
chatText += $"\n- {mod}";
}
HudManager.Instance.Chat.AddChat(PlayerControl.LocalPlayer, chatText, false);
if (DataManager.Settings.Multiplayer.ChatMode == QuickChatModes.FreeChatOrQuickChat)
{
var truncatedChatText = chatText.Length > ChatMessageLimit
? chatText[..(ChatMessageLimit - 3)] + "..."
: chatText;
// Write SendChat directly instead of using RpcSendChat so we can call AddChat ourselves
var messageWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte) RpcCalls.SendChat, SendOption.Reliable);
messageWriter.Write(truncatedChatText);
messageWriter.EndMessage();
}
innerNetClient.KickPlayer(clientData.Id, false);
}
innerNetClient.StartCoroutine(CoKick());
__result = false;
return false;
}
else if (!Mod.Validate(reactorClientData?.Mods ?? Array.Empty<Mod>(), ModList.Current, out var reason))
if (!Mod.Validate(reactorClientData.Mods, ModList.Current, out var reason))
{
innerNetClient.KickWithReason(clientData.Id, reason);
__result = false;
@@ -162,27 +118,23 @@ internal static class ClientPatches
}
}
[HarmonyPatch(typeof(InnerNetClient._CoSendSceneChange_d__156), nameof(InnerNetClient._CoSendSceneChange_d__156.MoveNext))]
[HarmonyPatch(typeof(InnerNetClient._CoSendSceneChange_d__30), nameof(InnerNetClient._CoSendSceneChange_d__30.MoveNext))]
public static class CoSendSceneChangePatch
{
public static bool Prefix(InnerNetClient._CoSendSceneChange_d__156 __instance, ref bool __result)
public static bool Prefix(InnerNetClient._CoSendSceneChange_d__30 __instance, ref bool __result)
{
if (ReactorConnection.Instance!.Syncer != Syncer.Host) return true;
var innerNetClient = __instance.__4__this;
// Check for the conditions when the scene change message should be sent
if (!innerNetClient.AmHost &&
innerNetClient.connection.State == ConnectionState.Connected &&
innerNetClient.ClientId >= 0)
if (__instance.__1__state == 2)
{
var clientData = innerNetClient.FindClientById(innerNetClient.ClientId);
if (clientData != null)
if (!innerNetClient.AmHost && innerNetClient.connection.State == ConnectionState.Connected)
{
var writer = MessageWriter.Get(SendOption.Reliable);
writer.StartMessage(Tags.GameData);
writer.Write(innerNetClient.GameId);
writer.StartMessage((byte) GameDataTypes.SceneChangeFlag);
writer.StartMessage(InnerNetClient.SceneChangeFlag);
writer.WritePacked(innerNetClient.ClientId);
writer.Write(__instance.sceneName);
@@ -195,25 +147,21 @@ internal static class ClientPatches
writer.EndMessage();
innerNetClient.SendOrDisconnect(writer);
writer.Recycle();
// Create a new coroutine to let AmongUsClient handle scene changes too
innerNetClient.StartCoroutine(innerNetClient.CoOnPlayerChangedScene(clientData, __instance.sceneName));
// Cancel this coroutine
__instance.__1__state = -1;
__result = false;
return false;
}
__instance.__1__state = -1;
__result = false;
return false;
}
return true;
}
}
[HarmonyPatch(typeof(InnerNetClient._CoHandleSpawn_d__166), nameof(InnerNetClient._CoHandleSpawn_d__166.MoveNext))]
[HarmonyPatch(typeof(InnerNetClient._CoHandleSpawn_d__40), nameof(InnerNetClient._CoHandleSpawn_d__40.MoveNext))]
public static class CoHandleSpawnPatch
{
public static void Postfix(InnerNetClient._CoHandleSpawn_d__166 __instance, bool __result)
public static void Postfix(InnerNetClient._CoHandleSpawn_d__40 __instance, bool __result)
{
if (ReactorConnection.Instance!.Syncer != Syncer.Host) return;
@@ -237,23 +185,47 @@ internal static class ClientPatches
}
}
[HarmonyPatch(typeof(SpawnGameDataMessage), nameof(SpawnGameDataMessage.SerializeValues))]
public static class SpawnGameDataMessagePatch
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.WriteSpawnMessage))]
public static class WriteSpawnMessagePatch
{
public static void Postfix(SpawnGameDataMessage __instance, MessageWriter msg)
public static bool Prefix(InnerNetClient __instance, InnerNetObject netObjParent, int ownerId, SpawnFlags flags, MessageWriter msg)
{
if (ReactorConnection.Instance!.Syncer != Syncer.Host)
if (ReactorConnection.Instance!.Syncer != Syncer.Host) return true;
msg.StartMessage(4);
msg.WritePacked(netObjParent.SpawnId);
msg.WritePacked(ownerId);
msg.Write((byte) flags);
InnerNetObject[] componentsInChildren = netObjParent.GetComponentsInChildren<InnerNetObject>();
msg.WritePacked(componentsInChildren.Length);
foreach (var innerNetObject in componentsInChildren)
{
return;
innerNetObject.OwnerId = ownerId;
innerNetObject.SpawnFlags = flags;
if (innerNetObject.NetId == 0)
{
innerNetObject.NetId = __instance.NetIdCnt++;
__instance.allObjects.Add(innerNetObject);
__instance.allObjectsFast.Add(innerNetObject.NetId, innerNetObject);
}
msg.WritePacked(innerNetObject.NetId);
msg.StartMessage(1);
innerNetObject.Serialize(msg, initialState: true);
msg.EndMessage();
}
// PATCH - Inject ReactorHandshakeS2C
if (AmongUsClient.Instance.ClientId != __instance.ownerId && __instance.NetObjectType == Il2CppType.Of<PlayerControl>())
if (__instance.ClientId != ownerId && IL2CPP.il2cpp_object_get_class(netObjParent.Pointer) == Il2CppClassPointerStore<PlayerControl>.NativeClassPtr)
{
Debug("Injecting ReactorHandshakeS2C to WriteSpawnMessage");
ReactorHeader.Write(msg);
ModdedHandshakeS2C.Serialize(msg, "Among Us", Application.version, 0); // TODO
}
msg.EndMessage();
return false;
}
}
@@ -262,10 +234,7 @@ internal static class ClientPatches
{
public static bool Prefix(InnerNetClient __instance, [HarmonyArgument(0)] MessageReader reader)
{
if (__instance.NetworkMode == NetworkModes.FreePlay)
{
return true;
}
if (__instance.GameMode == GameModes.FreePlay) return true;
var isFirst = false;
+29 -20
View File
@@ -5,6 +5,7 @@ using HarmonyLib;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Object = UnityEngine.Object;
namespace Reactor.Networking.Patches;
@@ -54,12 +55,8 @@ internal static class HttpPatches
public static void Prefix(UnityWebRequest __instance)
{
// new Uri() is necessary because uri property got stripped.
var path = new Uri(__instance.url).AbsolutePath;
// Public lobby menu uses /api/games/filtered, code requests use /api/games/code,
// creating a game uses /api/games.
// So we need to match everything that contains /api/games
if (path.Contains("/api/games"))
var path = __instance.uri.AbsolutePath;
if (path == "/api/games")
{
Debug($"{__instance.method} {path}");
__instance.SetRequestHeader("Client-Mods", BuildHeader());
@@ -68,12 +65,8 @@ internal static class HttpPatches
public static void Postfix(UnityWebRequest __instance, UnityWebRequestAsyncOperation __result)
{
// new Uri() is necessary because uri property got stripped.
var path = new Uri(__instance.url).AbsolutePath;
// Public lobby menu uses /api/games/filtered, code requests use /api/games/code,
// creating a game uses /api/games.
// So we need to match everything that contains /api/games
if (path.Contains("/api/games"))
var path = __instance.uri.AbsolutePath;
if (path == "/api/games")
{
__result.add_completed((Action<AsyncOperation>) (_ =>
{
@@ -92,9 +85,9 @@ internal static class HttpPatches
if (__instance.GetMethod() == UnityWebRequest.UnityWebRequestMethod.Get)
{
if (responseHeader == null && ModList.IsAnyModRequiredOnAllClients)
if (responseHeader == null)
{
HandshakePopup.Show();
DisconnectPopup.Instance.ShowCustom(Translate.Messages.VanillaServerWarning);
}
}
@@ -109,16 +102,32 @@ internal static class HttpPatches
{
public static void Postfix(GameStartManager __instance)
{
if (AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame) return;
if (ModList.IsAnyModRequiredOnAllClients && !IsCurrentRegionModded())
if (AmongUsClient.Instance.GameMode != GameModes.OnlineGame) return;
if (ModList.Current.Any(m => m.IsRequiredOnAllClients) && !IsCurrentRegionModded())
{
Warning("Vanilla region, locking public toggle");
__instance.HostPublicButton.enabled = false;
__instance.HostPrivateButton.transform.FindChild("Inactive").GetComponent<SpriteRenderer>().color = new Color(1, 1, 1, 0.5f);
__instance.MakePublicButtonBehaviour.enabled = false;
var actionMapGlyphDisplay = __instance.MakePublicButton.GetComponentInChildren<ActionMapGlyphDisplay>(includeInactive: true);
if (actionMapGlyphDisplay)
{
actionMapGlyphDisplay.gameObject.SetActive(value: false);
}
var onClick = __instance.HostPrivateButton.OnClick = new Button.ButtonClickedEvent();
onClick.AddListener((Action) MakePublicDisallowedPopup.Show);
__instance.MakePublicButton.color = new Color(1, 1, 1, 0.5f);
__instance.MakePublicButton.sprite = __instance.PrivateGameImage;
var onClick = __instance.MakePublicButton.GetComponent<PassiveButton>().OnClick = new Button.ButtonClickedEvent();
onClick.AddListener((Action) (() =>
{
var popup = Object.Instantiate(DiscordManager.Instance.discordPopup, Camera.main!.transform);
var background = popup.transform.Find("Background").GetComponent<SpriteRenderer>();
var size = background.size;
size.x *= 2.5f;
background.size = size;
popup.TextAreaTMP.fontSizeMin = 2;
popup.Show(Translate.Messages.PublicLobbyWarning);
}));
if (AmongUsClient.Instance.AmHost && AmongUsClient.Instance.IsGamePublic)
{
@@ -4,7 +4,7 @@ using InnerNet;
namespace Reactor.Networking.Patches;
internal sealed class ReactorClientData
internal class ReactorClientData
{
public ClientData ClientData { get; }
@@ -23,16 +23,12 @@ public class ReactorConnection
[HarmonyPatch]
private static class Patches
{
// CoConnect(string) was inlined, so we patch the MoveNext method instead.
[HarmonyPatch(typeof(InnerNetClient._CoConnect_d__65), nameof(InnerNetClient._CoConnect_d__65.MoveNext))]
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.CoConnect), typeof(string))]
[HarmonyPrefix]
public static void CoConnect()
{
if (Instance == null)
{
Debug("New ReactorConnection created");
Instance = new ReactorConnection();
}
Debug("New ReactorConnection created");
Instance = new ReactorConnection();
}
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.DisconnectInternal))]
+5 -20
View File
@@ -32,11 +32,13 @@ public class MethodRpc : UnsafeCustomRpc
/// <param name="id">The id of the rpc.</param>
/// <param name="option">The send option of the rpc.</param>
/// <param name="localHandling">The local handling method of the rpc.</param>
public MethodRpc(BasePlugin plugin, MethodInfo method, uint id, SendOption option, RpcLocalHandling localHandling) : base(plugin, id)
/// <param name="sendImmediately">The value indicating whether the rpc should be sent immediately.</param>
public MethodRpc(BasePlugin plugin, MethodInfo method, uint id, SendOption option, RpcLocalHandling localHandling, bool sendImmediately) : base(plugin, id)
{
Method = method;
LocalHandling = localHandling;
SendOption = option;
SendImmediately = sendImmediately;
var parameters = method.GetParameters();
@@ -69,22 +71,6 @@ public class MethodRpc : UnsafeCustomRpc
_handle = Hook(method, parameters, method.IsStatic);
}
/// <summary>
/// Initializes a new instance of the <see cref="MethodRpc"/> class.
/// </summary>
/// <param name="plugin">The plugin that the rpc is attached to.</param>
/// <param name="method">The method of the method rpc.</param>
/// <param name="id">The id of the rpc.</param>
/// <param name="option">The send option of the rpc.</param>
/// <param name="localHandling">The local handling method of the rpc.</param>
/// <param name="sendImmediately">The value indicating whether the rpc should be sent immediately.</param>
[Obsolete("Non-immediate RPCs were removed in 2025.5.20. All RPCs are immediate. Remove sendImmediately from the parameter list.")]
public MethodRpc(BasePlugin plugin, MethodInfo method, uint id, SendOption option, RpcLocalHandling localHandling, bool sendImmediately)
: this(plugin, method, id, option, localHandling)
{
SendImmediately = sendImmediately;
}
/// <summary>
/// Gets the method of the method rpc.
/// </summary>
@@ -105,8 +91,7 @@ public class MethodRpc : UnsafeCustomRpc
/// <summary>
/// Gets a value indicating whether the method rpc should be sent immediately.
/// </summary>
[Obsolete("Non-immediate RPCs were removed in 2025.5.20. All RPCs are immediate. This property will be removed in a future version.")]
public bool SendImmediately { get; } = true;
public bool SendImmediately { get; }
/// <inheritdoc />
public override void UnsafeWrite(MessageWriter writer, object? data)
@@ -149,7 +134,7 @@ public class MethodRpc : UnsafeCustomRpc
/// <param name="args">The arguments to serialize and send.</param>
public void Send(InnerNetObject innerNetObject, object[] args)
{
UnsafeSend(innerNetObject, args);
UnsafeSend(innerNetObject, args, SendImmediately);
}
private static readonly MethodInfo _sendMethod = AccessTools.Method(typeof(MethodRpc), nameof(Send));
+13 -11
View File
@@ -96,7 +96,7 @@ public abstract class UnsafeCustomRpc
/// <param name="ackCallback">The callback to invoke when this packet is acknowledged.</param>
public void UnsafeSend(InnerNetObject innerNetObject, object? data, bool immediately = false, int targetClientId = -1, Action? ackCallback = null)
{
ArgumentNullException.ThrowIfNull(innerNetObject);
if (innerNetObject == null) throw new ArgumentNullException(nameof(innerNetObject));
if (Manager == null)
{
@@ -108,16 +108,11 @@ public abstract class UnsafeCustomRpc
UnsafeHandle(innerNetObject, data);
}
if (immediately == false)
var writer = immediately switch
{
Warning("Non-immediate RPCs were removed in 2025.5.20! Reactor will now always send immediately!");
}
var writer = AmongUsClient.Instance.StartRpcImmediately(
innerNetObject.NetId,
CustomRpcManager.CallId,
SendOption,
targetClientId);
false => AmongUsClient.Instance.StartRpc(innerNetObject.NetId, CustomRpcManager.CallId, SendOption),
true => AmongUsClient.Instance.StartRpcImmediately(innerNetObject.NetId, CustomRpcManager.CallId, SendOption, targetClientId),
};
writer.Write(Mod);
writer.WritePacked(Id);
@@ -132,7 +127,14 @@ public abstract class UnsafeCustomRpc
AckCallbacks.TryAdd(writer, ackCallback);
}
AmongUsClient.Instance.FinishRpcImmediately(writer);
if (immediately)
{
AmongUsClient.Instance.FinishRpcImmediately(writer);
}
else
{
writer.EndMessage();
}
if (LocalHandling == RpcLocalHandling.After)
{
@@ -15,83 +15,33 @@ public static class MessageSerializer
private static List<UnsafeMessageConverter> MessageConverters { get; } = new();
private static Dictionary<Type, UnsafeMessageConverter?> MessageConverterMap { get; } = new();
private static Dictionary<Type, Type> GenericConvertersMap { get; } = new();
internal static void ClearMaps()
{
MessageConverterMap.Clear();
}
/// <summary>
/// Registers a MessageConverter.
/// </summary>
/// <param name="type">The Type of the MessageConverter to be registered.</param>
public static void Register(Type type)
/// <param name="messageConverter">The MessageConverter to be registered.</param>
public static void Register(UnsafeMessageConverter messageConverter)
{
if (type.IsGenericTypeDefinition)
{
var baseType = type.BaseType!;
if (!baseType.Name.Contains("MessageConverter"))
throw new InvalidOperationException($"{type.Name} should directly inherit from MessageConverter<T>");
var generics = baseType.GetGenericArguments();
var param = generics[0];
GenericConvertersMap.Add(param.GetGenericTypeDefinition(), type);
}
else
{
var messageConverter = (UnsafeMessageConverter) Activator.CreateInstance(type)!;
MessageConverters.Add(messageConverter);
}
MessageConverters.Add(messageConverter);
MessageConverterMap.Clear();
}
/// <summary>
/// Finds a MessageConverter for the specified <paramref name="type"/>.
/// </summary>
/// <param name="type">The type of an object.</param>
/// <returns>A MessageConverter that can convert the specified <see cref="Type"/>.</returns>
/// <returns>A MessageConverted that can convert the specified <see cref="Type"/>.</returns>
public static UnsafeMessageConverter? FindConverter(Type type)
{
if (!MessageConverterMap.TryGetValue(type, out var value))
if (MessageConverterMap.TryGetValue(type, out var value))
{
value = MessageConverters.SingleOrDefault(x => x.CanConvert(type));
if (value == null)
return null;
MessageConverterMap.Add(type, value);
return value;
}
return value;
}
var converter = MessageConverters.SingleOrDefault(x => x.CanConvert(type));
MessageConverterMap.Add(type, converter);
/// <summary>
/// Finds and builds a MessageConverter for the specified <paramref name="type"/> using a registered generic converter.
/// </summary>
/// <param name="type">The type of an object.</param>
/// <returns>A MessageConverter that can convert the specified <see cref="Type"/>.</returns>
public static UnsafeMessageConverter? FindGenericConverter(Type type)
{
if (MessageConverterMap.TryGetValue(type, out var value))
return value;
if (!type.IsGenericType)
return null;
var typeDef = type.GetGenericTypeDefinition();
if (!GenericConvertersMap.TryGetValue(typeDef, out var builder))
return null;
var generic = builder.MakeGenericType(type.GetGenericArguments());
value = (UnsafeMessageConverter) Activator.CreateInstance(generic)!;
MessageConverters.Add(value);
MessageConverterMap.Add(type, value);
return value;
return converter;
}
/// <summary>
@@ -99,7 +49,7 @@ public static class MessageSerializer
/// </summary>
/// <param name="writer">The <see cref="MessageWriter"/> to write to.</param>
/// <param name="args">The args to be written.</param>
public static void Serialize(this MessageWriter writer, params object[] args)
public static void Serialize(MessageWriter writer, object[] args)
{
foreach (var arg in args)
{
@@ -137,48 +87,24 @@ public static class MessageSerializer
case bool i:
writer.Write(i);
break;
case ulong i:
writer.Write(i);
break;
case long i:
ExtraMessageExtensions.Write(writer, i); // For some reason this insists on referring the to float write method, so this is me taking precautions
break;
case Vector2 i:
writer.Write(i);
break;
case string i:
writer.Write(i);
break;
case Color i:
writer.Write(i);
break;
case Color32 i:
writer.Write(i);
break;
case Enum i:
writer.Write(i);
break;
default:
var type = @object.GetType();
var converter = FindGenericConverter(type) ?? FindConverter(type);
var converter = FindConverter(@object.GetType());
if (converter != null)
{
converter.UnsafeWrite(writer, @object);
else
throw new NotSupportedException("Couldn't serialize " + type.Name);
break;
}
break;
throw new NotSupportedException("Couldn't serialize " + @object.GetType());
}
}
/// <summary>
/// Deserializes a generic <typeparamref name="T"/> value from the <paramref name="reader"/>.
/// </summary>
/// <param name="reader">The <see cref="MessageReader"/> to read from.</param>
/// <typeparam name="T">The type to be read.</typeparam>
/// <returns>A generic <typeparamref name="T"/> value from the <paramref name="reader"/>.</returns>
public static T Deserialize<T>(this MessageReader reader) => (T) reader.Deserialize(typeof(T));
/// <summary>
/// Deserializes an <see cref="object"/> of <paramref name="objectType"/> from the <paramref name="reader"/>.
/// </summary>
@@ -232,33 +158,7 @@ public static class MessageSerializer
return reader.ReadString();
}
if (objectType == typeof(ulong))
{
return reader.ReadUInt64();
}
if (objectType == typeof(long))
{
return reader.ReadInt64();
}
if (objectType == typeof(Color))
{
return reader.ReadColor();
}
if (objectType == typeof(Color32))
{
return reader.ReadColor32();
}
if (objectType.IsEnum)
{
return reader.ReadEnum(objectType);
}
var converter = FindGenericConverter(objectType) ?? FindConverter(objectType);
var converter = FindConverter(objectType);
if (converter != null)
{
return converter.UnsafeRead(reader, objectType);
-18
View File
@@ -1,18 +0,0 @@
using HarmonyLib;
namespace Reactor.Patches.Fixes;
/// <summary>
/// Fixes Game Lists not working on servers using legacy matchmaking.
/// </summary>
[HarmonyPatch(typeof(AmongUsClient_CoFindGame), nameof(AmongUsClient_CoFindGame.MoveNext))]
internal static class CoFindGamePatch
{
public static void Prefix()
{
if (AmongUsClient.Instance.LastDisconnectReason == DisconnectReasons.Unknown)
{
AmongUsClient.Instance.LastDisconnectReason = DisconnectReasons.ExitGame;
}
}
}
+1 -9
View File
@@ -1,6 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HarmonyLib;
using TMPro;
using UnityEngine;
@@ -10,20 +8,14 @@ namespace Reactor.Patches.Fixes;
/// <summary>
/// "Fixes" an issue where empty TextBoxes have wrong cursor positions.
/// </summary>
[HarmonyPatch]
[HarmonyPatch(typeof(TextMeshProExtensions), nameof(TextMeshProExtensions.CursorPos))]
internal static class CursorPosPatch
{
public static IEnumerable<MethodBase> TargetMethods()
{
return AccessTools.GetDeclaredMethods(typeof(TextMeshProExtensions)).Where(m => m.Name == nameof(TextMeshProExtensions.CursorPos));
}
public static bool Prefix(TextMeshPro self, ref Vector2 __result)
{
if (self.textInfo == null || self.textInfo.lineCount == 0 || self.textInfo.lineInfo[0].characterCount <= 0)
{
__result = self.GetTextInfo(" ").lineInfo.First().lineExtents.max;
self.text = string.Empty;
return false;
}
@@ -1,5 +1,3 @@
using System;
using System.Linq;
using HarmonyLib;
namespace Reactor.Patches.Miscellaneous;
@@ -7,38 +5,24 @@ namespace Reactor.Patches.Miscellaneous;
[HarmonyPatch]
internal static class CustomServersPatch
{
private static bool IsCurrentServerOfficial()
{
const string Domain = "among.us";
return ServerManager.Instance.CurrentRegion?.TryCast<StaticHttpRegionInfo>() is { } regionInfo &&
regionInfo.PingServer.EndsWith(Domain, StringComparison.Ordinal) &&
regionInfo.Servers.All(serverInfo => serverInfo.Ip.EndsWith(Domain, StringComparison.Ordinal));
}
[HarmonyPatch(typeof(AuthManager._CoConnect_d__4), nameof(AuthManager._CoConnect_d__4.MoveNext))]
[HarmonyPatch(typeof(AuthManager._CoWaitForNonce_d__6), nameof(AuthManager._CoWaitForNonce_d__6.MoveNext))]
[HarmonyPrefix]
public static bool DisableAuthServer(ref bool __result)
public static bool DisableAuthServer(out bool __result)
{
if (IsCurrentServerOfficial())
{
return true;
}
__result = false;
return false;
}
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__49), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__49.MoveNext))]
[HarmonyPatch(typeof(AmongUsClient._CoJoinOnlinePublicGame_d__1), nameof(AmongUsClient._CoJoinOnlinePublicGame_d__1.MoveNext))]
[HarmonyPrefix]
public static void EnableUdpMatchmaking(AmongUsClient._CoJoinOnlinePublicGame_d__49 __instance)
public static void EnableUdpMatchmaking(AmongUsClient._CoJoinOnlinePublicGame_d__1 __instance)
{
// Skip to state 1 which just calls CoJoinOnlineGameDirect
if (__instance.__1__state == 0 && !ServerManager.Instance.IsHttp)
{
__instance.__1__state = 1;
__instance.__8__1 = new AmongUsClient.__c__DisplayClass49_0
__instance.__8__1 = new AmongUsClient.__c__DisplayClass1_0
{
matchmakerToken = string.Empty,
};
@@ -1,41 +0,0 @@
using HarmonyLib;
using Reactor.Networking;
namespace Reactor.Patches.Miscellaneous;
[HarmonyPatch]
internal static class DisableServerAuthorityPatch
{
private const int DisableServerAuthorityFlag = 25;
public static bool Enabled => ModList.IsAnyModDisableServerAuthority || ReactorConfig.ForceDisableServerAuthority.Value;
[HarmonyPatch(typeof(Constants), nameof(Constants.GetBroadcastVersion))]
[HarmonyPostfix]
public static void GetBroadcastVersionPatch(ref int __result)
{
if (!Enabled) return;
if (AmongUsClient.Instance.NetworkMode != NetworkModes.OnlineGame) return;
Debug("Sending the DisableServerAuthority flag");
var revision = __result % 50;
if (revision < DisableServerAuthorityFlag)
{
__result += DisableServerAuthorityFlag;
}
}
[HarmonyPatch(typeof(Constants), nameof(Constants.IsVersionModded))]
[HarmonyPrefix]
public static bool IsVersionModdedPatch(ref bool __result)
{
if (Enabled)
{
__result = true;
return false;
}
return true;
}
}
@@ -30,17 +30,20 @@ internal static class FreeNamePatch
var editName = DestroyableSingleton<AccountManager>.Instance.accountTab.editNameScreen;
var nameText = Object.Instantiate(editName.nameText.gameObject);
nameText.transform.localPosition += Vector3.up * (AccountManager.Instance.isActiveAndEnabled ? 1.85f : 2.2f);
nameText.transform.localPosition += Vector3.up * 2.2f;
var textBox = nameText.GetComponent<TextBoxTMP>();
textBox.outputText.alignment = TextAlignmentOptions.CenterGeoAligned;
textBox.outputText.transform.position = nameText.transform.position;
textBox.outputText.fontSize = 4f;
textBox.OnChange.AddListener((Action) (() =>
{
DataManager.Player.Customization.Name = textBox.text;
}));
textBox.OnEnter = textBox.OnFocusLost = textBox.OnChange;
textBox.Pipe.GetComponent<TextMeshPro>().fontSize = 4f;
}));
}
@@ -53,10 +56,10 @@ internal static class FreeNamePatch
"JoinGameButton",
};
var yStart = Vector3.up * (AccountManager.Instance.isActiveAndEnabled ? 0.9f : 1.1f);
var yStart = Vector3.up;
var yOffset = Vector3.down * 1.5f;
var gameObjects = toMove.Select(x => GameObject.Find("NormalMenu/Buttons/" + x)).ToList();
var gameObjects = toMove.Select(x => GameObject.Find("NormalMenu/" + x)).ToList();
if (gameObjects.Any(x => x == null)) return false;
for (var i = 0; i < gameObjects.Count; i++)
@@ -1,21 +0,0 @@
using System;
using HarmonyLib;
using Reactor.Utilities;
namespace Reactor.Patches.Miscellaneous;
[HarmonyPatch(typeof(PingTracker), nameof(PingTracker.Update))]
internal static class PingTrackerPatch
{
[HarmonyPostfix]
[HarmonyPriority(Priority.Last)]
public static void Postfix(PingTracker __instance)
{
var extraText = ReactorCredits.GetText(ReactorCredits.Location.PingTracker);
if (extraText != null)
{
if (!__instance.text.text.EndsWith("\n", StringComparison.InvariantCulture)) __instance.text.text += "\n";
__instance.text.text += extraText;
}
}
}
+38 -58
View File
@@ -1,7 +1,7 @@
using System;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using Reactor.Utilities;
using HarmonyLib;
using Reactor.Utilities.Extensions;
using TMPro;
using UnityEngine;
@@ -25,86 +25,66 @@ public static class ReactorVersionShower
/// </summary>
public static event Action<TextMeshPro>? TextUpdated;
private static void SetMainMenuPositionFromAspect(float aspectRatio)
{
if (Text == null) return;
var pos = new Vector3(-1.2287f * aspectRatio + 10.9f, -0.57f, 4.5f);
Text.transform.position = pos;
}
private static readonly ResolutionManager.ResolutionChangedHandler _resolutionChangedHandler = (Action<float, int, int, bool>) ((aspectRatio, _, _, _) =>
{
SetMainMenuPositionFromAspect(aspectRatio);
});
internal static void Initialize()
{
SceneManager.add_sceneLoaded((Action<Scene, LoadSceneMode>) ((scene, _) =>
SceneManager.add_sceneLoaded((Action<Scene, LoadSceneMode>) ((_, _) =>
{
var original = UnityEngine.Object.FindObjectOfType<VersionShower>();
if (!original)
return;
var originalAspectPosition = original.GetComponent<AspectPosition>();
var originalText = original.GetComponentInChildren<TextMeshPro>();
var gameObject = new GameObject("ReactorVersion " + Guid.NewGuid());
gameObject.transform.parent = original.transform.parent;
var gameObject = new GameObject("ReactorVersion");
var aspectPosition = gameObject.AddComponent<AspectPosition>();
aspectPosition.Alignment = AspectPosition.EdgeAlignments.LeftTop;
var originalAspectPosition = original.GetComponent<AspectPosition>();
var originalPosition = originalAspectPosition.DistanceFromEdge;
originalPosition.y = 0.15f;
originalAspectPosition.DistanceFromEdge = originalPosition;
originalAspectPosition.AdjustPosition();
var position = originalPosition;
position.x += 10.075f - 0.1f;
position.y += 2.75f - 0.15f;
position.z -= 1;
aspectPosition.DistanceFromEdge = position;
aspectPosition.AdjustPosition();
Text = gameObject.AddComponent<TextMeshPro>();
Text.font = originalText.font;
Text.fontMaterial = originalText.fontMaterial;
Text.UpdateFontAsset();
Text.overflowMode = TextOverflowModes.Overflow;
Text.fontSize = 2;
Text.outlineWidth = 0.1f;
Text.enableWordWrapping = false;
Text.alignment = TextAlignmentOptions.TopLeft;
if (scene.name == "MainMenu")
{
ResolutionManager.add_ResolutionChanged(_resolutionChangedHandler);
SetMainMenuPositionFromAspect(Screen.width / (float) Screen.height);
}
else
{
ResolutionManager.remove_ResolutionChanged(_resolutionChangedHandler);
var aspectPosition = gameObject.AddComponent<AspectPosition>();
var distanceFromEdge = new Vector3(10.13f, 2.55f, -1);
if (originalAspectPosition.Alignment == AspectPosition.EdgeAlignments.LeftTop)
{
distanceFromEdge.y += 0.2f;
}
else if (AccountManager.Instance.isActiveAndEnabled)
{
distanceFromEdge.x += 0.2f;
distanceFromEdge.y += 0.575f;
}
aspectPosition.Alignment = AspectPosition.EdgeAlignments.LeftTop;
aspectPosition.DistanceFromEdge = distanceFromEdge;
aspectPosition.AdjustPosition();
}
UpdateText();
}));
}
private static string ToStringWithoutBuild(Version version)
{
return $"{version.Major}.{version.Minor}.{version.Patch}{(version.PreRelease == null ? string.Empty : $"-{version.PreRelease}")}";
}
/// <summary>
/// Updates <see cref="Text"/> with reactor version and fires <see cref="TextUpdated"/>.
/// </summary>
public static void UpdateText()
{
if (Text == null) return;
Text.text = "Reactor " + Version.Parse(ReactorPlugin.Version).WithoutBuild();
Text.text += "\nBepInEx " + Paths.BepInExVersion.WithoutBuild();
Text.text = "Reactor " + ReactorPlugin.Version;
Text.text += "\nBepInEx " + ToStringWithoutBuild(Paths.BepInExVersion);
Text.text += "\nMods: " + IL2CPPChainloader.Instance.Plugins.Count;
var creditsText = ReactorCredits.GetText(ReactorCredits.Location.MainMenu);
if (creditsText != null)
{
Text.text += "\n" + creditsText;
}
TextUpdated?.Invoke(Text);
}
[HarmonyPatch(typeof(FreeWeekendShower), nameof(FreeWeekendShower.Start))]
private static class FreeWeekendShowerPatch
{
public static bool Prefix(FreeWeekendShower __instance)
{
__instance.Output.Destroy();
return false;
}
}
}
+11
View File
@@ -1,19 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<LangVersion>latest</LangVersion>
<EnableDynamicLoading>true</EnableDynamicLoading>
<Description>Core mod and API for Among Us</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- SourceLink -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<ContinuousIntegrationBuild Condition="'$(GITHUB_ACTIONS)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<Compile Include="..\Reactor.Networking.Shared\**\*.cs" LinkBase="Networking" Visible="false" />
<PackageReference Include="Linguini.Bundle" Version="0.3.1" />
<ProjectReference Include="..\Reactor.Linguinitor\Reactor.Linguinitor.csproj" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\**\*" Exclude="Assets\icon.png" />
<AdditionalFiles Include="Assets\Localization\en\*.ftl" />
</ItemGroup>
<Import Project="../AmongUs.props" />
-22
View File
@@ -1,22 +0,0 @@
using BepInEx.Configuration;
namespace Reactor;
internal static class ReactorConfig
{
public const string FeaturesSection = "Features";
public const string MessagesSection = "Messages";
public static ConfigEntry<bool> ForceDisableServerAuthority { get; private set; } = null!;
public static ConfigEntry<string> HandshakePopupMessage { get; private set; } = null!;
public static ConfigEntry<string> MakePublicDisallowedPopupMessage { get; private set; } = null!;
public static void Bind(ConfigFile config)
{
ForceDisableServerAuthority = config.Bind(FeaturesSection, nameof(ForceDisableServerAuthority), false, "Enables the DisableServerAuthority flag even when no mods declare it");
HandshakePopupMessage = config.Bind(MessagesSection, nameof(HandshakePopupMessage), string.Empty);
MakePublicDisallowedPopupMessage = config.Bind(MessagesSection, nameof(MakePublicDisallowedPopupMessage), string.Empty);
}
}
+10 -5
View File
@@ -1,6 +1,8 @@
global using static Reactor.Utilities.Logger<Reactor.ReactorPlugin>;
using System;
using System.Linq;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
@@ -35,13 +37,15 @@ public partial class ReactorPlugin : BasePlugin
/// </summary>
public CustomRpcManager CustomRpcManager { get; } = new();
internal ConfigEntry<bool>? AllowVanillaServers { get; private set; }
internal RegionInfoWatcher RegionInfoWatcher { get; } = new();
internal FluentLocalizationProvider LocalizationProvider { get; } = FluentLocalizationProvider.FromEmbeddedResources("Reactor.Assets.Localization");
/// <inheritdoc />
public ReactorPlugin()
{
Log.LogMessage($"Among Us {Application.version} {Constants.GetCurrentPlatformName()}");
PluginSingleton<ReactorPlugin>.Instance = this;
PluginSingleton<BasePlugin>.Initialize();
@@ -53,12 +57,13 @@ public partial class ReactorPlugin : BasePlugin
MethodRpcAttribute.Initialize();
LocalizationManager.Register(new HardCodedLocalizationProvider());
LocalizationManager.Register(Translate.Provider = LocalizationProvider);
}
/// <inheritdoc />
public override void Load()
{
ReactorConfig.Bind(Config);
AllowVanillaServers = Config.Bind("Features", "Allow vanilla servers", false, "Whether reactor should ignore servers not responding to modded handshake. This config is ignored if any plugin uses custom rpcs!");
Harmony.PatchAll();
@@ -89,7 +94,7 @@ public partial class ReactorPlugin : BasePlugin
}
[RegisterInIl2Cpp]
private sealed class ReactorComponent : MonoBehaviour
private class ReactorComponent : MonoBehaviour
{
[HideFromIl2Cpp]
public ReactorPlugin? Plugin { get; internal set; }
@@ -107,7 +112,7 @@ public partial class ReactorPlugin : BasePlugin
foreach (var pluginInfo in IL2CPPChainloader.Instance.Plugins.Values)
{
var config = ((BasePlugin) pluginInfo.Instance).Config;
if (config.Count == 0)
if (!config.Any())
{
continue;
}
+30 -62
View File
@@ -3,8 +3,8 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MonoMod.Utils;
using Reactor.Utilities.Extensions;
using UnityEngine;
@@ -23,48 +23,38 @@ public static class AssetBundleManager
/// <summary>
/// Gets the target name of the current system.
/// </summary>
[Obsolete("Use AssetBundleManager#GetTargetName instead")]
public static string TargetName { get; } = GetTargetName(true);
public static string TargetName { get; }
/// <summary>
/// Gets the target name of the current system.
/// </summary>
/// <param name="includeArchitecture">A value indicating whether to include the process architecture.</param>
/// <returns>Target name of the current system.</returns>
public static string GetTargetName(bool includeArchitecture)
static AssetBundleManager()
{
string operatingSystem;
if (OperatingSystem.IsWindows())
if (PlatformHelper.Is(Platform.Android))
{
operatingSystem = "win";
}
else if (OperatingSystem.IsLinux())
{
operatingSystem = "linux";
}
else if (OperatingSystem.IsAndroid())
{
operatingSystem = "android";
TargetName = "android";
}
else
{
throw new PlatformNotSupportedException();
}
if (PlatformHelper.Is(Platform.Windows))
{
TargetName = "win";
}
else if (PlatformHelper.Is(Platform.Linux))
{
TargetName = "linux";
}
else
{
throw new PlatformNotSupportedException();
}
if (!includeArchitecture)
{
return operatingSystem;
if (PlatformHelper.Is(Platform.ARM))
{
TargetName += Environment.Is64BitProcess ? "-arm64" : "-arm";
}
else
{
TargetName += Environment.Is64BitProcess ? "-x64" : "-x86";
}
}
return $"{operatingSystem}-{RuntimeInformation.ProcessArchitecture switch
{
Architecture.X86 => "x86",
Architecture.X64 => "x64",
Architecture.Arm => "arm",
Architecture.Arm64 => "arm64",
_ => throw new PlatformNotSupportedException(),
}}";
}
/// <summary>
@@ -72,16 +62,7 @@ public static class AssetBundleManager
/// </summary>
/// <param name="assetBundleName">The name of the asset bundle.</param>
/// <returns>File name of the asset bundle.</returns>
[Obsolete("Use the overload with includeArchitecture instead")]
public static string GetFileName(string assetBundleName) => GetFileName(assetBundleName, true);
/// <summary>
/// Gets the file name for an asset bundle named <paramref name="assetBundleName"/>.
/// </summary>
/// <param name="assetBundleName">The name of the asset bundle.</param>
/// <param name="includeArchitecture">A value indicating whether to include the process architecture.</param>
/// <returns>File name of the asset bundle.</returns>
public static string GetFileName(string assetBundleName, bool includeArchitecture) => $"{assetBundleName}-{GetTargetName(includeArchitecture)}{BundleExtension}";
public static string GetFileName(string assetBundleName) => $"{assetBundleName}-{TargetName}{BundleExtension}";
private static bool TryFindFile(Assembly assembly, string fileName, [NotNullWhen(true)] out string? path)
{
@@ -91,7 +72,6 @@ public static class AssetBundleManager
var filePath = Path.Combine(pluginDirectoryPath, fileName);
if (File.Exists(filePath))
{
Debug($"Loading an asset bundle from {filePath}");
path = filePath;
return true;
}
@@ -106,8 +86,6 @@ public static class AssetBundleManager
var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.Ordinal));
if (resourceName != null)
{
Debug($"Loading an asset bundle from {resourceName}");
using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Resource stream was null");
var length = (int) stream.Length;
@@ -141,13 +119,8 @@ public static class AssetBundleManager
/// <exception cref="AssetBundleNotFoundException">Couldn't find an assetbundle named <paramref name="name"/>.</exception>
public static AssetBundle Load(Assembly assembly, string name)
{
return TryLoad(assembly, GetFileName(name, includeArchitecture: true))
?? TryLoad(assembly, GetFileName(name, includeArchitecture: false))
?? throw new AssetBundleNotFoundException(name);
}
var fileName = GetFileName(name);
private static AssetBundle? TryLoad(Assembly assembly, string fileName)
{
if (TryFindFile(assembly, fileName, out var filePath))
{
return AssetBundle.LoadFromFile(filePath);
@@ -158,7 +131,7 @@ public static class AssetBundleManager
return AssetBundle.LoadFromMemory(data);
}
return null;
throw new AssetBundleNotFoundException(name);
}
/// <summary>
@@ -181,13 +154,8 @@ public static class AssetBundleManager
/// <exception cref="AssetBundleNotFoundException">Couldn't find an assetbundle named <paramref name="name"/>.</exception>
public static AssetBundleCreateRequest LoadAsync(Assembly assembly, string name)
{
return TryLoadAsync(assembly, GetFileName(name, includeArchitecture: true))
?? TryLoadAsync(assembly, GetFileName(name, includeArchitecture: false))
?? throw new AssetBundleNotFoundException(name);
}
var fileName = GetFileName(name);
private static AssetBundleCreateRequest? TryLoadAsync(Assembly assembly, string fileName)
{
if (TryFindFile(assembly, fileName, out var filePath))
{
return AssetBundle.LoadFromFileAsync(filePath);
@@ -198,7 +166,7 @@ public static class AssetBundleManager
return AssetBundle.LoadFromMemoryAsync(data);
}
return null;
throw new AssetBundleNotFoundException(name);
}
}
+2 -1
View File
@@ -1,3 +1,4 @@
using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
@@ -51,6 +52,6 @@ public static class CanvasUtilities
/// <returns>An empty texture of specified size.</returns>
public static Texture2D CreateEmptyTexture(int width = 0, int height = 0)
{
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false);
return new Texture2D(width, height, TextureFormat.RGBA32, Texture.GenerateAllMips, false, IntPtr.Zero);
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ namespace Reactor.Utilities;
public static class Coroutines
{
[RegisterInIl2Cpp]
internal sealed class Component : MonoBehaviour
internal class Component : MonoBehaviour
{
internal static Component? Instance { get; set; }
@@ -1,40 +0,0 @@
namespace Reactor.Utilities.Extensions;
/// <summary>
/// Provides extension methods for TestMeshPro's Rich Text.
/// </summary>
internal static class RichTextExtensions
{
private static string Wrap(this string text, string tag)
{
return $"<{tag}>{text}</{tag}>";
}
private static string Wrap(this string text, string tag, string value)
{
return $"<{tag}={value}>{text}</{tag}>";
}
public static string Align(this string text, string value)
{
return text.Wrap("align", value);
}
public static string Color(this string text, string value)
{
return text.Wrap("color", value);
}
public static string Size(this string text, string value)
{
return text.Wrap("size", value);
}
public static string EscapeRichText(this string text)
{
return text
.Replace("<noparse>", string.Empty)
.Replace("</noparse>", string.Empty)
.Wrap("noparse");
}
}
@@ -1,19 +0,0 @@
using SemanticVersioning;
namespace Reactor.Utilities.Extensions;
/// <summary>
/// Provides extension methods for <see cref="SemanticVersioning.Version"/>.
/// </summary>
public static class VersionExtensions
{
/// <summary>
/// Gets the provided <paramref name="version"/> without the build string (everything after the + symbol like the commit hash is stripped).
/// </summary>
/// <param name="version">The <see cref="SemanticVersioning.Version"/>.</param>
/// <returns>The <paramref name="version"/> without build.</returns>
public static Version WithoutBuild(this Version version)
{
return new Version(version.Major, version.Minor, version.Patch, version.PreRelease);
}
}
+2 -3
View File
@@ -9,7 +9,7 @@ namespace Reactor.Utilities.ImGui;
/// </summary>
public class Window
{
private static int _lastWindowId = 2135184938;
private static int _lastWindowId;
/// <summary>
/// Gets the next window id.
@@ -75,8 +75,7 @@ public class Window
Rect = Rect.ResetSize();
}
GUI.skin.label.wordWrap = false;
Rect = GUILayout.Window(Id, Rect, Func, Title, GUILayout.MinWidth(GUI.skin.label.CalcSize(new GUIContent(Title)).x * 2));
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)))
{
-123
View File
@@ -1,123 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BepInEx.Unity.IL2CPP;
using Reactor.Patches;
using Reactor.Utilities.Extensions;
namespace Reactor.Utilities;
/// <summary>
/// Provides a way for mods to show their version information in-game.
/// </summary>
public static class ReactorCredits
{
private readonly struct ModIdentifier(string name, string version, Func<Location, bool>? shouldShow, bool isPreRelease)
{
private const string NormalColor = "#fff";
private const string PreReleaseColor = "#f00";
public string Name => name;
public string Text { get; } = $"{name} {version}".EscapeRichText().Color(isPreRelease ? PreReleaseColor : NormalColor);
public bool ShouldShow(Location location)
{
return shouldShow == AlwaysShow || shouldShow(location);
}
}
private static readonly List<ModIdentifier> _modIdentifiers = [];
/// <summary>
/// Represents the location of where the credit is shown.
/// </summary>
public enum Location
{
/// <summary>
/// In the main menu under Reactor/BepInEx versions.
/// </summary>
MainMenu,
/// <summary>
/// During game under the ping tracker.
/// </summary>
PingTracker,
}
/// <summary>
/// A special value indicating a mod should always show.
/// </summary>
public const Func<Location, bool>? AlwaysShow = null;
/// <summary>
/// Registers a mod with the <see cref="ReactorCredits"/>, adding it to the list of mods that will be displayed.
/// </summary>
/// <param name="name">The user-friendly name of the mod. Can contain spaces or special characters.</param>
/// <param name="version">The version of the mod.</param>
/// <param name="isPreRelease">If this version is a development or beta version. If true, it will display the mod in red.</param>
/// <param name="shouldShow">
/// This function will be called every frame to determine if the mod should be displayed or not.
/// This function should return false if your mod is currently disabled or has no effect on gameplay at the time.
/// If you want the mod to be displayed at all times, you can set this parameter to <see cref="ReactorCredits.AlwaysShow"/>.
/// </param>
public static void Register(string name, string version, bool isPreRelease, Func<Location, bool>? shouldShow)
{
const int MaxLength = 60;
if (name.Length + version.Length > MaxLength)
{
Error($"Not registering mod \"{name}\" with version \"{version}\" in {nameof(ReactorCredits)} because the combined length of the mod name and version is greater than {MaxLength} characters.");
return;
}
if (_modIdentifiers.Any(m => m.Name == name))
{
Error($"Mod \"{name}\" is already registered in {nameof(ReactorCredits)}.");
return;
}
_modIdentifiers.Add(new ModIdentifier(name, version, shouldShow, isPreRelease));
_modIdentifiers.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
if (!isPreRelease)
{
Info($"Mod \"{name}\" registered in {nameof(ReactorCredits)} with version {version}.");
}
else
{
Warning($"Mod \"{name}\" registered in {nameof(ReactorCredits)} with DEVELOPMENT/BETA version {version}.");
}
ReactorVersionShower.UpdateText();
}
/// <summary>
/// Registers a mod with the <see cref="ReactorCredits"/>, adding it to the list of mods that will be displayed.
/// </summary>
/// <typeparam name="T">The BepInEx plugin type to get the name and version from.</typeparam>
/// <param name="shouldShow"><inheritdoc cref="Register(string,string,bool,System.Func{Location,bool})" path="/param[@name='shouldShow']"/></param>
public static void Register<T>(Func<Location, bool>? shouldShow) where T : BasePlugin
{
var pluginInfo = IL2CPPChainloader.Instance.Plugins.Values.SingleOrDefault(p => p.TypeName == typeof(T).FullName)
?? throw new ArgumentException("Couldn't find the metadata for the provided plugin type", nameof(T));
var metadata = pluginInfo.Metadata;
Register(metadata.Name, metadata.Version.WithoutBuild().Clean(), metadata.Version.IsPreRelease, shouldShow);
}
internal static string? GetText(Location location)
{
var modTexts = _modIdentifiers.Where(m => m.ShouldShow(location)).Select(m => m.Text).ToArray();
if (modTexts.Length == 0) return null;
return location switch
{
Location.MainMenu => string.Join('\n', modTexts),
Location.PingTracker => ("<space=3em>" + string.Join(", ", modTexts)).Size("50%").Align("center"),
_ => throw new ArgumentOutOfRangeException(nameof(location), location, null),
};
}
}
+1 -1
View File
@@ -7,7 +7,7 @@ using Object = UnityEngine.Object;
namespace Reactor.Utilities;
internal sealed class RegionInfoWatcher : IDisposable
internal class RegionInfoWatcher : IDisposable
{
private FileSystemWatcher Watcher { get; }
-58
View File
@@ -1,58 +0,0 @@
using Il2CppInterop.Runtime.Attributes;
using Reactor.Utilities.Attributes;
using TMPro;
using UnityEngine;
namespace Reactor.Utilities.UI;
/// <summary>
/// Wrapper over <see cref="GenericPopup"/> that adds hyperlink and controller support.
/// </summary>
[RegisterInIl2Cpp]
internal sealed class ReactorPopup : MonoBehaviour
{
private readonly Il2CppSystem.Collections.Generic.List<SelectableHyperLink> _selectableHyperLinks = new();
public GenericPopup Popup { get; private set; } = null!;
public TextMeshPro TextArea { get; private set; } = null!;
public PassiveButton BackButton { get; private set; } = null!;
public SpriteRenderer Background { get; private set; } = null!;
[HideFromIl2Cpp]
public void Show(string text)
{
Popup.Show(text);
ControllerManager.Instance.OpenOverlayMenu(name, BackButton);
SelectableHyperLinkHelper.AddSelectableUiForHyperlinks(_selectableHyperLinks, name);
TextArea.text = SelectableHyperLinkHelper.DecomposeAnnouncementText(TextArea, _selectableHyperLinks, name, TextArea.text);
SelectableHyperLinkHelper.UpdateHyperlinkPositions(TextArea, _selectableHyperLinks, name);
ControllerManager.Instance.AddSelectableUiElement(BackButton, true);
}
public void OnDisable()
{
ControllerManager.Instance.CloseOverlayMenu(name);
}
[HideFromIl2Cpp]
public static ReactorPopup Create(string name)
{
var genericPopup = Instantiate(DiscordManager.Instance.discordPopup, Camera.main!.transform);
var gameObject = genericPopup.gameObject;
var reactorPopup = gameObject.AddComponent<ReactorPopup>();
reactorPopup.Popup = genericPopup;
reactorPopup.TextArea = genericPopup.TextAreaTMP;
reactorPopup.BackButton = gameObject.transform.Find("ExitGame").GetComponent<PassiveButton>();
reactorPopup.Background = gameObject.transform.Find("Background").GetComponent<SpriteRenderer>();
gameObject.name = name;
genericPopup.destroyOnClose = true;
reactorPopup.TextArea.fontSizeMin = 2;
return reactorPopup;
}
}
+129 -122
View File
@@ -4,9 +4,9 @@
"net6.0": {
"AmongUs.GameLibs.Steam": {
"type": "Direct",
"requested": "[2025.4.15, )",
"resolved": "2025.4.15",
"contentHash": "R3RxzHGZOGUJ9nMwrP0cjS6g+sh60QUU506Mo47lh17155enUjH6PtErijihSoU7t3aQpzCIyC67W3XrrHhH4g=="
"requested": "[2022.10.25, )",
"resolved": "2022.10.25",
"contentHash": "PWgkH/VvMlShVhZB8G432q0tnMaNVZrbIdbEMCZN/fETUlT/ch+qQj4PdTcZhPHREbnJHH3ijHxlca1d7QMBcQ=="
},
"BepInEx.AutoPlugin": {
"type": "Direct",
@@ -16,111 +16,84 @@
},
"BepInEx.IL2CPP.MSBuild": {
"type": "Direct",
"requested": "[2.1.0-rc.1, )",
"resolved": "2.1.0-rc.1",
"contentHash": "WI/7TbJwWl5P4B6UXGtKI1VMe6fA6h3fcbp3ZjJKqOBQ5MJfDMmeVB4fb+RW1tUQdxnlSWV3Ul62PHFyTqp4PA=="
"requested": "[2.0.1, )",
"resolved": "2.0.1",
"contentHash": "hUZjCV0t8dkw/Z/zq4Zl405QP7frBk/LVfMdUmUz+7XOhGd7lYPKrR48A5vbGl2QeHudMxlkXzAr9WM3Duq2SQ=="
},
"BepInEx.Unity.IL2CPP": {
"type": "Direct",
"requested": "[6.0.0-be.735, )",
"resolved": "6.0.0-be.735",
"contentHash": "2+eFJGKMR1GFPeU9wuF+TVrMANIaWIc/6N9e8x4b7b/fNiY9B6vicYNiMDb2deYQpWZtOei+2btnar5dDE5BPg==",
"requested": "[6.0.0-be.662, )",
"resolved": "6.0.0-be.662",
"contentHash": "fn7jQ88IBmjssoY9XjGBTg3cULkS+N/le/eUijYf2VV8raWok/6cU/GbU9bejkJS8g+2MvzIwnROAhAxvrGI2Q==",
"dependencies": {
"BepInEx.Core": "6.0.0-be.735",
"BepInEx.Unity.Common": "6.0.0-be.735",
"HarmonyX": "2.10.2",
"Iced": "1.21.0",
"Il2CppInterop.Generator": "1.4.6-ci.426",
"Il2CppInterop.HarmonySupport": "1.4.6-ci.426",
"Il2CppInterop.Runtime": "1.4.6-ci.426",
"MonoMod.RuntimeDetour": "22.7.31.1",
"Samboy063.Cpp2IL.Core": "2022.1.0-pre-release.19"
"BepInEx.Core": "6.0.0-be.662",
"BepInEx.Unity.Common": "6.0.0-be.662",
"HarmonyX": "2.10.0",
"Iced": "1.17.0",
"Il2CppInterop.Generator": "1.3.0",
"Il2CppInterop.HarmonySupport": "1.3.0",
"Il2CppInterop.Runtime": "1.3.0",
"MonoMod.RuntimeDetour": "22.5.1.1",
"Samboy063.Cpp2IL.Core": "2022.0.7.2"
}
},
"Linguini.Bundle": {
"type": "Direct",
"requested": "[0.3.1, )",
"resolved": "0.3.1",
"contentHash": "k3D0IBSsS91T0G9rYACRYtAS27NDTGz4T3ygHhbhaFdA9i3cCfCpR39MqYEpoA1Ark3lzmvklHePmRCX5EQi1A==",
"dependencies": {
"Linguini.Shared": "0.3.0",
"Linguini.Syntax": "0.3.0"
}
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[1.1.1, )",
"resolved": "1.1.1",
"contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==",
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.1",
"Microsoft.SourceLink.Common": "1.1.1"
}
},
"StyleCop.Analyzers": {
"type": "Direct",
"requested": "[1.2.0-beta.556, )",
"resolved": "1.2.0-beta.556",
"contentHash": "llRPgmA1fhC0I0QyFLEcjvtM2239QzKr/tcnbsjArLMJxJlu0AA5G7Fft0OI30pHF3MW63Gf4aSSsjc5m82J1Q==",
"requested": "[1.2.0-beta.435, )",
"resolved": "1.2.0-beta.435",
"contentHash": "TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.556"
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"AsmResolver": {
"AssetRipper.VersionUtilities": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "M5btCR/rmrx32jZsoN6CLQ/VQk8lN8hvPb6lgojua7pjNoo7StAl92koMC8qz4vzZyH2CNqxLSDoswRvyyK/vA=="
},
"AsmResolver.DotNet": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "PTq8nNQvhgTxF1iARCknffCsu7Iq9B0kN7TVC8iMaU7uEYog3xvVqH/0+TreY8GW74/+MqhZt/yEFsvS4oAduQ==",
"dependencies": {
"AsmResolver.PE": "6.0.0-beta.1"
}
},
"AsmResolver.PE": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "KadLvx/zzFCJyF+E4jG6jPE1d0iJquzL6+hm8GBivBAs6nwHC8s6g4c857QwQCzXMWza6Vz5Q+3hFiNuOfKaWQ==",
"dependencies": {
"AsmResolver.PE.File": "6.0.0-beta.1"
}
},
"AsmResolver.PE.File": {
"type": "Transitive",
"resolved": "6.0.0-beta.1",
"contentHash": "+lusB9UMHevI5aQsu73NQ1ctPMLFvyHAsEf8vjaJ/py+kX1DkU0JkbERtBRmaf58/hBZ7cyrE7gFnjoo7Bbg7A==",
"dependencies": {
"AsmResolver": "6.0.0-beta.1"
}
},
"AssetRipper.CIL": {
"type": "Transitive",
"resolved": "1.1.2",
"contentHash": "BRPcHORadIzSFkrVOvGkSs54j19mQdXH8dmRTVM51mS8MZLSbTpi9CDPpnWN2IdDsILUrAqbPUFo3zJodYxErw==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1"
}
},
"AssetRipper.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.3.2",
"contentHash": "wOr5PQPL/2ZfD7+ebt6cpRbUhSzSY5nlHGHjjzuQRiU5zkQlqQNwWDLX0M3smrm5IkaDvONkmDjFMKTlZJmyuQ=="
},
"AssetRipper.Primitives": {
"type": "Transitive",
"resolved": "3.1.3",
"contentHash": "djZbN/+EXmI+Oia9Pm0LyjZVCPLf60TPSL5rGb7mBEYM5F4CN3nPFXvl2yA5LanPZoHS1Yq7PghGUmkP7Pv9RQ=="
"resolved": "1.2.1",
"contentHash": "knQ/W1YwTZS2AbdaZh+nhyyBEZQPQDcahhSOnh88i+cdg4/FEoFJiCwaavgFvCMNuUeHTbcZc4qttF8WQ8xLIA=="
},
"BepInEx.Core": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "FuHm9UCzjSKeiZJc3IF70Fiuqi+FynRn62PwBoOeZcHK3/qm+vl1YwbZyFlmUyf45g+UKxg2Td40iZGx88LVAQ==",
"resolved": "6.0.0-be.662",
"contentHash": "VVBeCD/KQVy0/TK3V6SD8QZ/es35Xb1mEz/+PbBs3ST1yUC1r7k2JOymhSnmghVqf6UsvlMglOO9pljqhuE/Pw==",
"dependencies": {
"HarmonyX": "2.10.2",
"MonoMod.Utils": "22.7.31.1",
"HarmonyX": "2.10.0",
"MonoMod.Utils": "22.5.1.1",
"SemanticVersioning": "2.0.2"
}
},
"BepInEx.Unity.Common": {
"type": "Transitive",
"resolved": "6.0.0-be.735",
"contentHash": "vmK//OBSr+jotqTk//HSdvHtMFTKu+NlQkiEsvr0dZApTVmQM2AgpVMhEAakQPmrSsM6LRJIHCBcLFO1ypfMPQ==",
"resolved": "6.0.0-be.662",
"contentHash": "BgETw6+snwY//3xjQxLiiEAFRmXaMTcSkg+1UQz6fVBG0YA5Usm/m4GflhTc3nwF61KO3Iznn1AORi5CwLJoUw==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"MonoMod.Utils": "22.7.31.1"
"AssetRipper.VersionUtilities": "1.2.1",
"MonoMod.Utils": "22.5.1.1"
}
},
"Disarm": {
"type": "Transitive",
"resolved": "2022.1.0-master.57",
"contentHash": "/dkg7hg8iPBQN4bTV1lMQacarH6fMpgUXhJuo6iI7Wv7YpH7g5F9hJfje7dSMhqG0YlDacLuyWvcph5GzKUXog=="
},
"HarmonyX": {
"type": "Transitive",
"resolved": "2.10.2",
"contentHash": "/5WwkxXX8mPsRuigQt957rJGx1f0dDQxk+bvk4yYITKFjXas9Em+O71zEP8X0ym8OFQQ2XH/2SxS4NC7vEC+Xg==",
"resolved": "2.10.0",
"contentHash": "4ayiy/dlCiW86K2N7Jvbf+VpI5wvP7dncv/6oRmfwRi32UCmCRzCGzsxdMfzJZkp6/26oBW+DrD8vi4UejzVAg==",
"dependencies": {
"MonoMod.RuntimeDetour": "22.3.23.4",
"System.Reflection.Emit": "4.7.0"
@@ -128,13 +101,13 @@
},
"Iced": {
"type": "Transitive",
"resolved": "1.21.0",
"contentHash": "dv5+81Q1TBQvVMSOOOmRcjJmvWcX3BZPZsIq31+RLc5cNft0IHAyNlkdb7ZarOWG913PyBoFDsDXoCIlKmLclg=="
"resolved": "1.17.0",
"contentHash": "8x+HCVTl/HHTGpscH3vMBhV8sknN/muZFw9s3TsI8SA6+c43cOTCi2+jE4KsU8pNLbJ++iF2ZFcpcXHXtDglnw=="
},
"Il2CppInterop.Common": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "pI0kU0qqJKMP6z9eFz4+WJtGIwklfPxW2yWEY9vKnrN9bbYMusK3v5uFWV8al7S/HPSATV5jNWH1hyTvP7kglA==",
"resolved": "1.3.0",
"contentHash": "IR3BrZXvL2nvJAn4pruPMgC78Y87hVa5xTYZCuHN67OzRD6WDl5dTO55vtvTl8dXFALKvlN+spja2tXhVuquOw==",
"dependencies": {
"Iced": "1.17.0",
"Microsoft.Extensions.Logging.Abstractions": "6.0.1",
@@ -143,31 +116,59 @@
},
"Il2CppInterop.Generator": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "kecdx/vbNl0RtfzfYW592jU8PMyq1JbzpvoJSvqwO+tV6icp9SljXy6yG8bT/wt0gaPj9mFUNDTe2Wu6M6XGZQ==",
"resolved": "1.3.0",
"contentHash": "FuhPxbh/K4K94U3xac/ClMaaBp+MZ4aIaqi5dR0QihyGQoombT+OM/A22RwAIzbaCTbFbvabWaAuOSgB69ZwWQ==",
"dependencies": {
"Il2CppInterop.Common": "1.4.6-ci.426",
"Il2CppInterop.Common": "1.3.0",
"Mono.Cecil": "0.11.3"
}
},
"Il2CppInterop.HarmonySupport": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "rd2T5o6SybIc12hmX3HktTF5n27hFb0w4mNSExq7h1YsmrNlt7x+Ac1MBnnB0JwPLIg7w8LjnKjoIX6Gf626ng==",
"resolved": "1.3.0",
"contentHash": "VppBnXtbMNGFhX8a1gg/85E883t2pW/+FZyV7eOaOXMNQyorg++u+kUFOIYwNpzTVqxWmMeoPS0DH0toVpjoKA==",
"dependencies": {
"HarmonyX": "2.10.0",
"Il2CppInterop.Runtime": "1.4.6-ci.426"
"Il2CppInterop.Runtime": "1.3.0"
}
},
"Il2CppInterop.Runtime": {
"type": "Transitive",
"resolved": "1.4.6-ci.426",
"contentHash": "0O0oI7gOqJixrsjvh1firhuGYK3Yr0uDLp6Q+t5CfcTMmeEX8Plk3pqAP9ZYyilBvh7uW0gv4Golqz08L1GXug==",
"resolved": "1.3.0",
"contentHash": "8A+N2yvja960Ap+s2RpW7Nb6HSpyuXJy2ipIlU+1erYU9SWHMyU9JZzUZGOhwWXJChKGvRmDdTZAg12k1+72dg==",
"dependencies": {
"Iced": "1.17.0",
"Il2CppInterop.Common": "1.4.6-ci.426"
"Il2CppInterop.Common": "1.3.0"
}
},
"IndexRange": {
"type": "Transitive",
"resolved": "1.0.0",
"contentHash": "6TgS1JLSUkpmPLfXBPaAgB39ZUix8E4soXWk2XSDcscVe84i1JKzIAtA7jHbRHSkOOrcr6YA0MpLCeq98y9mYQ=="
},
"js6pak.Gee.External.Capstone": {
"type": "Transitive",
"resolved": "2.1.0",
"contentHash": "YYpq7NM50bSSVUDjXyV/eiITk6syXqItPjKBOb3jEWS6RFsk0DNhpWMPW6b3hKDmArARuWDU6S2pVu1IeVrvIA=="
},
"Linguini.Shared": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "rEYA9jWU1Nc9iDuPKar+4IVXjFbGrcNyYZCeU6hiWQoS4nA2UecHu36Rp4bxzasvRGda4FB2JZqty75m4e26VQ=="
},
"Linguini.Syntax": {
"type": "Transitive",
"resolved": "0.3.0",
"contentHash": "v8YV3xPFZfP+OSWjMd6yysp+o7cNnQXxq/slN8Yekoi+dFjsTNF0YiQWJIwg1j2FUbs6claJxY9R1FFlc4s6MA==",
"dependencies": {
"Linguini.Shared": "0.3.0"
}
},
"Microsoft.Build.Tasks.Git": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q=="
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "6.0.1",
@@ -183,6 +184,11 @@
"resolved": "1.1.0",
"contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg=="
},
"Microsoft.SourceLink.Common": {
"type": "Transitive",
"resolved": "1.1.1",
"contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg=="
},
"Mono.Cecil": {
"type": "Transitive",
"resolved": "0.11.4",
@@ -190,11 +196,11 @@
},
"MonoMod.RuntimeDetour": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nxVJTvQbWAujaogt5XX3eAy7d22t66Z88aWg9sirPLO9rR/6yNCHAyZpgxXrOsIobZVW0IEZPqNMOBhgke25/w==",
"resolved": "22.5.1.1",
"contentHash": "WG5zLRuAr8KJEnIkKTuIG1OJCrGIT3pjvnAD43E0FDchHf3Dp985MF/8tmIQvAzCZV87JNs6QKeGGqmwDmpXpw==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"MonoMod.Utils": "22.7.31.1",
"MonoMod.Utils": "22.5.1.1",
"System.Collections.NonGeneric": "4.3.0",
"System.ComponentModel.TypeConverter": "4.3.0",
"System.IO.FileSystem.Primitives": "4.3.0",
@@ -205,8 +211,8 @@
},
"MonoMod.Utils": {
"type": "Transitive",
"resolved": "22.7.31.1",
"contentHash": "nI0E1oadXS1iMbfwfCzYF08C1jRQR9cnnHv66a4BSPd4sGu2p6g4BmctCWsdAB6oGKkSJUhcfHfxcfTsDyB94Q==",
"resolved": "22.5.1.1",
"contentHash": "vBObO1atXxhi2C4AuC53y87Bqeogi9xIrD1Ym3YWr5uxc8Nrm8SrsFeD1i3x04R999+XQ3FdeHrbXScyWYEHqQ==",
"dependencies": {
"Mono.Cecil": "0.11.4",
"System.Collections.NonGeneric": "4.3.0",
@@ -317,46 +323,42 @@
},
"Samboy063.Cpp2IL.Core": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "mAYIrMo0VdOZzh1NS5bZeflg80gtYNY7kZo9q/blEYheUPyLXu5ozQOjX+Bq2yDh40pA+yiE2MXTnN2Is2hjgw==",
"resolved": "2022.0.7.2",
"contentHash": "e17CAhKSxdAp7vFcYEVxjSc7t7rcvVGBipGhgE9tAjRXY85wZXLlHEVO0AEvMRkLmf9U+if4wK/nZEC1AX6VqQ==",
"dependencies": {
"AsmResolver.DotNet": "6.0.0-beta.1",
"AssetRipper.CIL": "1.1.2",
"AssetRipper.Gee.External.Capstone": "2.3.2",
"Disarm": "2022.1.0-master.57",
"Iced": "1.21.0",
"Samboy063.LibCpp2IL": "2022.1.0-pre-release.19",
"StableNameDotNet": "0.1.0-pre-release.19"
"HarmonyX": "2.5.5",
"Iced": "1.11.1",
"IndexRange": "1.0.0",
"Mono.Cecil": "0.11.4",
"Samboy063.LibCpp2IL": "2022.0.7.2",
"System.Runtime.InteropServices": "4.3.0",
"System.ValueTuple": "4.5.0",
"js6pak.Gee.External.Capstone": "2.1.0"
}
},
"Samboy063.LibCpp2IL": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "/n8p81ltd38BeNNS2xUNPGMSzxk/UGXr9cRNqG1MaLogzANNNrvCAXqWmNMM3tZctjp7vqTxEA+e4J4ngul8Fg==",
"resolved": "2022.0.7.2",
"contentHash": "DpVeU0dQkUJCpbw0f1xKOG8vimdK2oYhrVABC7HDE3/ikGjhnMZd3i5b1joKDHZ+AiL90TWOaEXPcy24rCZ0dA==",
"dependencies": {
"AssetRipper.Primitives": "3.1.3",
"Samboy063.WasmDisassembler": "2022.1.0-pre-release.19"
"IndexRange": "1.0.0",
"Samboy063.WasmDisassembler": "2022.0.2"
}
},
"Samboy063.WasmDisassembler": {
"type": "Transitive",
"resolved": "2022.1.0-pre-release.19",
"contentHash": "uVQdYm/J6+jJ1xt6GJ3hNhXhciwlX+LmHTPITu9jjZ75T33YJuuTD7pLVYuMymr+4gSVisg7f1wterFSyqJBWA=="
"resolved": "2022.0.2",
"contentHash": "2uu+xBb7M3HKfBx9tAY6jiDieAf0hRnQjSmGX+7IdE6i24dYsx6TYgtrLvRx5lOuF2M8DijZ5H8yQ1pcuCs2SA=="
},
"SemanticVersioning": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4EQgYdNZ92SyaO7YFk6olVnebF5V+jrHyMUjvPq89tLeMo8NSfgDF+6Zwq/lgh9j/0yfQp9Lkm0ZA0rUATCZFA=="
},
"StableNameDotNet": {
"type": "Transitive",
"resolved": "0.1.0-pre-release.19",
"contentHash": "5BPWtntv3PXeFIg9CuGW6OM3f5GnwvdQJbzRpufPsistFwFyt1xYW1wSDr+QIdDO7vLndr7iNpWD3FyYp9LL4g=="
},
"StyleCop.Analyzers.Unstable": {
"type": "Transitive",
"resolved": "1.2.0.556",
"contentHash": "zvn9Mqs/ox/83cpYPignI8hJEM2A93s2HkHs8HYMOAQW0PkampyoErAiIyKxgTLqbbad29HX/shv/6LGSjPJNQ=="
"resolved": "1.2.0.435",
"contentHash": "ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg=="
},
"System.Collections": {
"type": "Transitive",
@@ -899,6 +901,11 @@
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
}
},
"System.ValueTuple": {
"type": "Transitive",
"resolved": "4.5.0",
"contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ=="
}
}
}
-6
View File
@@ -1,6 +0,0 @@
{
"sdk": {
"version": "8.0.0",
"rollForward": "latestFeature"
}
}
-1
View File
@@ -3,6 +3,5 @@
<configuration>
<packageSources>
<add key="BepInEx" value="https://nuget.bepinex.dev/v3/index.json" />
<add key="Samboy" value="https://nuget.samboy.dev/v3/index.json" />
</packageSources>
</configuration>