-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
1,068 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
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(); | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
Reactor.Debugger/AutoJoin/AutoJoinConnectionListener.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
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(); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
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)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#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(); | ||
} |
Oops, something went wrong.