Supports url address and ipv6 connecting
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
using System.Net;
|
||||
using Godot;
|
||||
using MegaCrit.Sts2.Core.Nodes.GodotExtensions;
|
||||
|
||||
namespace SlayTheSpire2.LAN.Multiplayer.Components
|
||||
{
|
||||
internal class AddressLineEdit : NMegaLineEdit
|
||||
{
|
||||
public override void _Ready()
|
||||
{
|
||||
TextSubmitted += OnTextSubmitted;
|
||||
}
|
||||
|
||||
public struct AddressInfo(bool isValid, string? address, ushort? port)
|
||||
{
|
||||
public bool IsValid = isValid;
|
||||
public string? Address = address;
|
||||
public ushort? Port = port;
|
||||
}
|
||||
|
||||
public AddressInfo GetAddressInfo()
|
||||
{
|
||||
var addressInfo = new AddressInfo();
|
||||
|
||||
var uriString = Text;
|
||||
|
||||
if (uriString == "localhost")
|
||||
{
|
||||
uriString = $"http://{uriString}";
|
||||
}
|
||||
|
||||
if (Uri.TryCreate(uriString, UriKind.Absolute, out var uri) && uri.Scheme is "http" or "https")
|
||||
{
|
||||
addressInfo.IsValid = true;
|
||||
addressInfo.Address = uri.Host;
|
||||
|
||||
if (uri is { Port: > -1, IsDefaultPort: false })
|
||||
{
|
||||
addressInfo.Port = (ushort)uri.Port;
|
||||
}
|
||||
|
||||
return addressInfo;
|
||||
}
|
||||
|
||||
if (IPAddress.TryParse(Text, out _))
|
||||
{
|
||||
addressInfo.IsValid = true;
|
||||
addressInfo.Address = Text;
|
||||
}
|
||||
else if (IPEndPoint.TryParse(Text, out var ipEndPoint))
|
||||
{
|
||||
addressInfo.IsValid = true;
|
||||
addressInfo.Port = (ushort)ipEndPoint.Port;
|
||||
}
|
||||
|
||||
return addressInfo;
|
||||
}
|
||||
|
||||
private void OnTextSubmitted(string newText)
|
||||
{
|
||||
Modulate = Colors.White;
|
||||
|
||||
if (GetAddressInfo().IsValid)
|
||||
return;
|
||||
|
||||
Modulate = Colors.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Godot;
|
||||
using MegaCrit.Sts2.Core.Nodes.GodotExtensions;
|
||||
|
||||
namespace SlayTheSpire2.LAN.Multiplayer.Components
|
||||
{
|
||||
internal partial class IPAddressLineEdit : NMegaLineEdit
|
||||
{
|
||||
[GeneratedRegex(@"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$")]
|
||||
private static partial Regex IPRegex();
|
||||
|
||||
[GeneratedRegex(
|
||||
@"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.){3}(25[0-5]|(2[0-4]|1\d|[1-9]|)\d):((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([1-9][0-9]{0,3})|[0-9])$")]
|
||||
private static partial Regex IPAndPortRegex();
|
||||
|
||||
[GeneratedRegex("^[0-9.:]*$")]
|
||||
private static partial Regex IPAllowRegex();
|
||||
|
||||
private string _oldText = "";
|
||||
|
||||
public bool IsOnlyIP => IPRegex().IsMatch(Text);
|
||||
|
||||
public bool IsIPAndPort => IPAndPortRegex().IsMatch(Text);
|
||||
|
||||
public string? IPAddress => IsOnlyIP ? Text : IsIPAndPort ? Text.Split(':').First() : null;
|
||||
|
||||
public ushort? Port => IsIPAndPort ? Convert.ToUInt16(Text.Split(':').Last()) : null;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
TextChanged += OnTextChanged;
|
||||
TextSubmitted += OnTextSubmitted;
|
||||
}
|
||||
|
||||
private void OnTextChanged(string newText)
|
||||
{
|
||||
if (IPAllowRegex().IsMatch(newText))
|
||||
{
|
||||
_oldText = newText;
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = _oldText;
|
||||
CaretColumn = Text.Length;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextSubmitted(string newText)
|
||||
{
|
||||
Modulate = Colors.White;
|
||||
|
||||
if (IPRegex().IsMatch(newText))
|
||||
return;
|
||||
|
||||
if (IPAndPortRegex().IsMatch(newText))
|
||||
return;
|
||||
|
||||
Modulate = Colors.Red;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,8 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
return false;
|
||||
}
|
||||
|
||||
private static async Task<NetErrorInfo?> ConnectToHost(ENetClient eNetClient, Logger logger, INetClientHandler handler, ulong netId, string ip, ushort port, CancellationToken cancelToken)
|
||||
private static async Task<NetErrorInfo?> ConnectToHost(ENetClient eNetClient, Logger logger,
|
||||
INetClientHandler handler, ulong netId, string ip, ushort port, CancellationToken cancelToken)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@@ -34,7 +35,8 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
var peer = connection.ConnectToHost(ip, port);
|
||||
Traverse.Create(eNetClient).Field("_peer").SetValue(peer);
|
||||
var timeoutTimer = 0;
|
||||
while (!connection.TryService(out var output) || output is not { type: ENetConnection.EventType.Connect })
|
||||
while (!connection.TryService(out var output) ||
|
||||
output is not { type: ENetConnection.EventType.Connect })
|
||||
{
|
||||
await Task.Delay(100, cancelToken);
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
@@ -60,7 +62,8 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
}
|
||||
|
||||
var bufferedPackets = new List<ENetServiceData>();
|
||||
var (result, newNetId) = await SendAndWaitForNetIdAck(eNetClient, logger, peer, connection, netId, bufferedPackets, cancelToken);
|
||||
var (result, newNetId) = await SendAndWaitForNetIdAck(eNetClient, logger, peer, connection, netId,
|
||||
bufferedPackets, cancelToken);
|
||||
if (result.HasValue)
|
||||
{
|
||||
peer.PeerDisconnect();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections;
|
||||
using Godot;
|
||||
using HarmonyLib;
|
||||
using MegaCrit.Sts2.Core.Entities.Multiplayer;
|
||||
using MegaCrit.Sts2.Core.Helpers;
|
||||
using MegaCrit.Sts2.Core.Multiplayer.Transport;
|
||||
using MegaCrit.Sts2.Core.Multiplayer.Transport.ENet;
|
||||
@@ -97,4 +98,25 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ENetHost), "StartHost")]
|
||||
internal class ENetHostStartHostPatch
|
||||
{
|
||||
private static bool Prefix(ushort port, int maxClients, Logger ____logger, ref ENetConnection? ____connection,
|
||||
ref bool ____isConnected, ref NetErrorInfo? __result)
|
||||
{
|
||||
____connection = new ENetConnection();
|
||||
var error = ____connection.CreateHostBound("*", port, maxClients);
|
||||
if (error != Error.Ok)
|
||||
{
|
||||
____logger.Error($"Failed to create host! {error}");
|
||||
__result = new NetErrorInfo(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
____isConnected = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,14 +62,14 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
ipAddressLabel.SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter;
|
||||
}
|
||||
|
||||
var ipAddressLineEdit = new IPAddressLineEdit { Name = "IPInput" };
|
||||
var addressLineEdit = new AddressLineEdit { Name = "AddressInput" };
|
||||
|
||||
vBoxContainer.AddChild(ipAddressLineEdit);
|
||||
vBoxContainer.AddChild(addressLineEdit);
|
||||
|
||||
ipAddressLineEdit.Text = SettingsHelper.Instance.SettingsModel.IPAddress;
|
||||
ipAddressLineEdit.Alignment = HorizontalAlignment.Center;
|
||||
ipAddressLineEdit.CustomMinimumSize = new Vector2(300, 50);
|
||||
ipAddressLineEdit.SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter;
|
||||
addressLineEdit.Text = SettingsHelper.Instance.SettingsModel.IPAddress;
|
||||
addressLineEdit.Alignment = HorizontalAlignment.Center;
|
||||
addressLineEdit.CustomMinimumSize = new Vector2(300, 50);
|
||||
addressLineEdit.SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter;
|
||||
|
||||
if (__instance.GetNode<NJoinFriendRefreshButton>("RefreshButton").Duplicate() is NJoinFriendRefreshButton
|
||||
joinButton)
|
||||
@@ -83,28 +83,27 @@ namespace SlayTheSpire2.LAN.Multiplayer.Patchs
|
||||
|
||||
joinButton.Connect(NClickableControl.SignalName.Released, Callable.From<NClickableControl>(_ =>
|
||||
{
|
||||
if (!ipAddressLineEdit.IsOnlyIP &&
|
||||
(!ipAddressLineEdit.IsIPAndPort || !ipAddressLineEdit.Port.HasValue))
|
||||
var addressInfo = addressLineEdit.GetAddressInfo();
|
||||
|
||||
if (!addressInfo.IsValid)
|
||||
return;
|
||||
|
||||
SettingsHelper.Instance.SettingsModel.IPAddress = ipAddressLineEdit.Text;
|
||||
SettingsHelper.Instance.SettingsModel.IPAddress = addressLineEdit.Text;
|
||||
SettingsHelper.Instance.WriteSettings();
|
||||
|
||||
var ipAddress = ipAddressLineEdit.IPAddress;
|
||||
ushort port = 33771;
|
||||
|
||||
if (ipAddressLineEdit.Port.HasValue)
|
||||
if (addressInfo.Port.HasValue)
|
||||
{
|
||||
port = ipAddressLineEdit.Port.Value;
|
||||
port = addressInfo.Port.Value;
|
||||
}
|
||||
|
||||
var netId = SettingsHelper.Instance.SettingsModel.NetId;
|
||||
|
||||
DisplayServer.WindowSetTitle("Slay The Spire 2 (Client)");
|
||||
if (ipAddress != null)
|
||||
if (addressInfo.Address != null)
|
||||
{
|
||||
TaskHelper.RunSafely(
|
||||
__instance.JoinGameAsync(new ENetClientConnectionInitializer(netId, ipAddress, port)));
|
||||
__instance.JoinGameAsync(new ENetClientConnectionInitializer(
|
||||
SettingsHelper.Instance.SettingsModel.NetId, addressInfo.Address, port)));
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
<Reference Include="GodotSharp">
|
||||
<HintPath>V:\Slay.the.Spire.2\game\data_sts2_windows_x86_64\GodotSharp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Steamworks.NET">
|
||||
<HintPath>V:\Slay.the.Spire.2\game\data_sts2_windows_x86_64\Steamworks.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="sts2">
|
||||
<HintPath>V:\Slay.the.Spire.2\game\data_sts2_windows_x86_64\sts2.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
Reference in New Issue
Block a user