Fixed IdCollision HandshakeResponse will not send
Added ConnectToHost auto try NetID feature
This commit is contained in:
@@ -22,27 +22,9 @@ namespace SlayTheSpire2.LAN.Multiplayer.Components
|
|||||||
|
|
||||||
public bool IsIPAndPort => IPAndPortRegex().IsMatch(Text);
|
public bool IsIPAndPort => IPAndPortRegex().IsMatch(Text);
|
||||||
|
|
||||||
public string? IPAddress
|
public string? IPAddress => IsOnlyIP ? Text : IsIPAndPort ? Text.Split(':').First() : null;
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsOnlyIP)
|
|
||||||
return Text;
|
|
||||||
|
|
||||||
return IsIPAndPort ? Text.Split(':').First() : null;
|
public ushort? Port => IsIPAndPort ? Convert.ToUInt16(Text.Split(':').Last()) : null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ushort? Port
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (IsIPAndPort)
|
|
||||||
return Convert.ToUInt16(Text.Split(':').Last());
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using MegaCrit.Sts2.Core.Entities.Multiplayer;
|
||||||
|
using MegaCrit.Sts2.Core.Helpers;
|
||||||
|
using MegaCrit.Sts2.Core.Logging;
|
||||||
|
using MegaCrit.Sts2.Core.Multiplayer;
|
||||||
|
using MegaCrit.Sts2.Core.Multiplayer.Connection;
|
||||||
|
using MegaCrit.Sts2.Core.Multiplayer.Transport.ENet;
|
||||||
|
using MegaCrit.Sts2.Core.Platform;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
// ReSharper disable UnusedType.Global
|
||||||
|
|
||||||
|
namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(ENetClientConnectionInitializer), "Connect")]
|
||||||
|
internal class ENetClientConnectionInitializerPatch
|
||||||
|
{
|
||||||
|
private static bool Prefix(NetClientGameService gameService,
|
||||||
|
CancellationToken cancelToken, ulong ____netId, string ____ip, ushort ____port, ref Task __result)
|
||||||
|
{
|
||||||
|
__result = TaskHelper.RunSafely(Connect(gameService, cancelToken, ____netId, ____ip, ____port));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<NetErrorInfo?> Connect(NetClientGameService gameService,
|
||||||
|
CancellationToken cancelToken, ulong netId, string ip, ushort port)
|
||||||
|
{
|
||||||
|
if (gameService.IsConnected)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
"NetClientGameService must not be connected when passed to ENetClientConnectionInitializer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var eNetClient = new ENetClient(gameService);
|
||||||
|
gameService.Initialize(eNetClient, PlatformType.None);
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
const int tryCount = 10;
|
||||||
|
NetErrorInfo? netErrorInfo = null;
|
||||||
|
|
||||||
|
while (count < tryCount)
|
||||||
|
{
|
||||||
|
if (cancelToken.IsCancellationRequested)
|
||||||
|
return netErrorInfo;
|
||||||
|
|
||||||
|
netErrorInfo = await eNetClient.ConnectToHost(netId, ip, port, cancelToken);
|
||||||
|
|
||||||
|
if (!netErrorInfo.HasValue)
|
||||||
|
{
|
||||||
|
Log.Info($"Connect {ip}:{port} Host Game NetID:{netId}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (netErrorInfo.Value.GetReason() != NetError.Kicked)
|
||||||
|
return netErrorInfo;
|
||||||
|
|
||||||
|
var nextNetId = netId + 1000u;
|
||||||
|
|
||||||
|
if (count < tryCount - 1)
|
||||||
|
{
|
||||||
|
Log.Warn($"{ip}:{port} Host Game NetID:{netId} already occupied, next try NetID:{nextNetId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
netId = nextNetId;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return netErrorInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
using Godot;
|
||||||
|
using HarmonyLib;
|
||||||
|
using MegaCrit.Sts2.Core.Multiplayer.Transport.ENet;
|
||||||
|
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
// ReSharper disable UnusedType.Global
|
||||||
|
|
||||||
|
namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||||
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
|
internal class ENetHostDoClientHandshakePatch
|
||||||
|
{
|
||||||
|
private static MethodInfo TargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.AsyncMoveNext(typeof(ENetHost).GetMethod("DoClientHandshake",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
|
{
|
||||||
|
//Fixed IdCollision HandshakeResponse will not send
|
||||||
|
|
||||||
|
var peerDisconnectMethod = AccessTools.Method(typeof(ENetPacketPeer), "PeerDisconnect");
|
||||||
|
var peerDisconnectLaterMethod = AccessTools.Method(typeof(ENetPacketPeer), "PeerDisconnectLater");
|
||||||
|
|
||||||
|
foreach (var instruction in instructions)
|
||||||
|
{
|
||||||
|
if (instruction.opcode == OpCodes.Callvirt && instruction.operand as MethodInfo == peerDisconnectMethod)
|
||||||
|
{
|
||||||
|
yield return new CodeInstruction(OpCodes.Callvirt, peerDisconnectLaterMethod);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return instruction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user