Skip to content

Commit c259e3c

Browse files
authored
Introduce INetManager (#779)
* Introduce INetManager * Remove MultiplayerServer.TickEvent No longer necessary * Split off LiteNetArbiterManager from LiteNetManager * Remove INetManager.OnServerStop * Extract server LAN management into it's own manager * Add diagnostic info to INetManager * Remove INetManager.Start Gets rid of two-step initialization * Remove GetFreePort helper from ServerTest * Minor test cleanup
1 parent 8e97cd3 commit c259e3c

File tree

9 files changed

+303
-168
lines changed

9 files changed

+303
-168
lines changed

Source/Client/Networking/HostUtil.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ private static void PrepareLocalServer(ServerSettings settings, bool fromReplay)
6565
localServer.worldData.hostFactionId = Faction.OfPlayer.loadID;
6666
localServer.worldData.spectatorFactionId = Multiplayer.WorldComp.spectatorFaction.loadID;
6767

68-
if (settings.steam)
69-
localServer.TickEvent += SteamP2PIntegration.ServerSteamNetTick;
70-
7168
if (fromReplay)
7269
{
7370
localServer.gameTimer = TickPatch.Timer;
@@ -218,9 +215,11 @@ private static void StartArbiter()
218215
{
219216
Multiplayer.session.AddMsg("The Arbiter instance is starting...", false);
220217

221-
Multiplayer.LocalServer.liteNet.SetupArbiterConnection();
218+
var arbiterNet = LiteNetArbiterManager.Create(Multiplayer.LocalServer);
219+
if (arbiterNet == null) throw new Exception("Failed to setup Arbiter network.");
220+
Multiplayer.LocalServer.netManagers.Add(arbiterNet);
222221

223-
string args = $"-batchmode -nographics -arbiter -logfile arbiter_log.txt -connect=127.0.0.1:{Multiplayer.LocalServer.liteNet.ArbiterPort}";
222+
string args = $"-batchmode -nographics -arbiter -logfile arbiter_log.txt -connect=127.0.0.1:{arbiterNet.Port}";
224223

225224
if (GenCommandLine.TryGetCommandLineArg("savedatafolder", out string saveDataFolder))
226225
args += $" \"-savedatafolder={saveDataFolder}\"";

Source/Client/Networking/NetworkingSteam.cs

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Multiplayer.Common;
66
using Steamworks;
77
using Verse;
8+
using Verse.Steam;
89

910
namespace Multiplayer.Client.Networking
1011
{
@@ -101,6 +102,66 @@ private void OnDisconnect()
101102
}
102103
}
103104

105+
public class SteamP2PNetManager : INetManager
106+
{
107+
private readonly MultiplayerServer server;
108+
109+
private SteamP2PNetManager(MultiplayerServer server) => this.server = server;
110+
111+
public static SteamP2PNetManager Create(MultiplayerServer server)
112+
{
113+
if (!SteamManager.Initialized) return null;
114+
return new SteamP2PNetManager(server);
115+
}
116+
117+
public void Tick()
118+
{
119+
foreach (var packet in SteamP2PIntegration.ReadPackets(0))
120+
{
121+
var playerManager = server.playerManager;
122+
var player = playerManager.Players
123+
.FirstOrDefault(p => p.conn is SteamBaseConn conn && conn.remoteId == packet.remote);
124+
125+
if (packet.joinPacket && player == null)
126+
{
127+
ConnectionBase conn = new SteamServerConn(packet.remote, packet.channel);
128+
129+
var preConnect = playerManager.OnPreConnect(packet.remote);
130+
if (preConnect != null)
131+
{
132+
conn.Close(preConnect.Value);
133+
continue;
134+
}
135+
136+
conn.ChangeState(ConnectionStateEnum.ServerJoining);
137+
player = playerManager.OnConnected(conn);
138+
player.type = PlayerType.Steam;
139+
140+
player.steamId = (ulong)packet.remote;
141+
player.steamPersonaName = SteamFriends.GetFriendPersonaName(packet.remote);
142+
if (player.steamPersonaName.Length == 0)
143+
player.steamPersonaName = "[unknown]";
144+
145+
conn.Send(Packets.Server_SteamAccept);
146+
}
147+
148+
if (!packet.joinPacket && player != null)
149+
{
150+
player.HandleReceive(packet.data, packet.reliable);
151+
}
152+
}
153+
}
154+
155+
public void Stop()
156+
{
157+
// Managed externally by Steamworks
158+
}
159+
160+
public string GetDiagnosticsName() => "SteamP2P";
161+
162+
public string GetDiagnosticsInfo() => null;
163+
}
164+
104165
public static class SteamP2PIntegration
105166
{
106167
private static Callback<P2PSessionConnectFail_t> p2pFail;
@@ -161,43 +222,5 @@ internal static IEnumerable<SteamPacket> ReadPackets(int recvChannel)
161222
};
162223
}
163224
}
164-
165-
public static void ServerSteamNetTick(MultiplayerServer server)
166-
{
167-
foreach (var packet in ReadPackets(0))
168-
{
169-
var playerManager = server.playerManager;
170-
var player = playerManager.Players
171-
.FirstOrDefault(p => p.conn is SteamBaseConn conn && conn.remoteId == packet.remote);
172-
173-
if (packet.joinPacket && player == null)
174-
{
175-
ConnectionBase conn = new SteamServerConn(packet.remote, packet.channel);
176-
177-
var preConnect = playerManager.OnPreConnect(packet.remote);
178-
if (preConnect != null)
179-
{
180-
conn.Close(preConnect.Value);
181-
continue;
182-
}
183-
184-
conn.ChangeState(ConnectionStateEnum.ServerJoining);
185-
player = playerManager.OnConnected(conn);
186-
player.type = PlayerType.Steam;
187-
188-
player.steamId = (ulong)packet.remote;
189-
player.steamPersonaName = SteamFriends.GetFriendPersonaName(packet.remote);
190-
if (player.steamPersonaName.Length == 0)
191-
player.steamPersonaName = "[unknown]";
192-
193-
conn.Send(Packets.Server_SteamAccept);
194-
}
195-
196-
if (!packet.joinPacket && player != null)
197-
{
198-
player.HandleReceive(packet.data, packet.reliable);
199-
}
200-
}
201-
}
202225
}
203226
}

Source/Client/Windows/ChatWindow.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -383,11 +383,11 @@ void LogNetData(string name, NetStatistics stats)
383383

384384
if (Multiplayer.LocalServer != null)
385385
{
386-
if (Multiplayer.LocalServer.liteNet.lanManager != null)
387-
LogNetData("Lan Server", Multiplayer.LocalServer.liteNet.lanManager.Statistics);
388-
389-
//if (Multiplayer.LocalServer.net.netManager != null)
390-
// LogNetData("Net Server", Multiplayer.LocalServer.net.netManager.Statistics);
386+
foreach (var man in Multiplayer.LocalServer.netManagers)
387+
{
388+
text.AppendLine(man.GetDiagnosticsName());
389+
text.AppendLine(man.GetDiagnosticsInfo() ?? "<no info>");
390+
}
391391

392392
// todo thread problems?
393393
// foreach (var p in Multiplayer.LocalServer.players.ToList())

Source/Client/Windows/HostWindow.cs

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Collections.Generic;
33
using System.IO;
44
using System.Linq;
5+
using System.Net;
6+
using Multiplayer.Client.Networking;
57
using Multiplayer.Client.Util;
68
using Multiplayer.Common;
79
using Multiplayer.Common.Util;
@@ -464,25 +466,89 @@ static bool TryParseEndpoints(ServerSettings settings)
464466
static bool TryStartLocalServer(ServerSettings settings)
465467
{
466468
var localServer = new MultiplayerServer(settings);
467-
var success = localServer.liteNet.StartNet();
469+
var success = true;
468470

469-
if (success)
471+
if (settings.direct) {
472+
var liteNet = StartLiteNetManager(localServer, settings);
473+
if (liteNet == null) success = false;
474+
else localServer.netManagers.Add(liteNet);
475+
}
476+
477+
if (settings.lan)
478+
{
479+
var lan = StartLanManager(localServer, settings);
480+
if (lan == null) success = false;
481+
else localServer.netManagers.Add(lan);
482+
}
483+
484+
if (settings.steam)
470485
{
471-
Multiplayer.LocalServer = localServer;
472-
return true;
486+
var steam = StartSteamP2PManager(localServer, settings);
487+
if (steam == null) success = false;
488+
else localServer.netManagers.Add(steam);
473489
}
474490

475-
foreach (var (endpoint, man) in localServer.liteNet.netManagers)
491+
if (!success)
492+
{
493+
localServer.netManagers.ForEach(man => man.Stop());
494+
return false;
495+
}
496+
497+
Multiplayer.LocalServer = localServer;
498+
return true;
499+
}
500+
501+
private static INetManager StartLiteNetManager(MultiplayerServer server, ServerSettings settings)
502+
{
503+
var invalidEndpoint = settings.TryParseEndpoints(out var endpoints);
504+
if (invalidEndpoint != null)
505+
{
506+
Messages.Message(
507+
"MpInvalidEndpoint".Translate(invalidEndpoint),
508+
MessageTypeDefOf.RejectInput,
509+
false
510+
);
511+
return null;
512+
}
513+
514+
if (LiteNetManager.Create(server, endpoints, out var liteNet)) return liteNet;
515+
516+
foreach (var (endpoint, man) in liteNet.netManagers)
476517
{
477518
if (man.IsRunning) continue;
478519
Messages.Message($"Failed to bind direct on {endpoint}", MessageTypeDefOf.RejectInput, false);
479520
}
480521

481-
if (localServer.liteNet.lanManager is { IsRunning: false })
482-
Messages.Message($"Failed to bind LAN on {settings.lanAddress}", MessageTypeDefOf.RejectInput, false);
522+
liteNet.Stop();
523+
return null;
524+
}
525+
526+
public static INetManager StartLanManager(MultiplayerServer server, ServerSettings settings)
527+
{
528+
if (!IPAddress.TryParse(settings.lanAddress, out var ipAddr))
529+
{
530+
Messages.Message(
531+
"MpInvalidEndpoint".Translate(settings.lanAddress),
532+
MessageTypeDefOf.RejectInput,
533+
false
534+
);
535+
return null;
536+
}
537+
538+
var man = LiteNetLanManager.Create(server, ipAddr);
539+
if (man != null) return man;
540+
541+
Messages.Message($"Failed to bind LAN on {settings.lanAddress}", MessageTypeDefOf.RejectInput, false);
542+
return null;
543+
}
544+
545+
public static INetManager StartSteamP2PManager(MultiplayerServer server, ServerSettings settings)
546+
{
547+
var man = SteamP2PNetManager.Create(server);
548+
if (man != null) return man;
483549

484-
localServer.liteNet.StopNet();
485-
return false;
550+
Messages.Message("Failed to start Steam networking", MessageTypeDefOf.RejectInput, false);
551+
return null;
486552
}
487553

488554
public override void PostClose()

Source/Common/INetManager.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace Multiplayer.Common;
2+
3+
public interface INetManager
4+
{
5+
public void Tick();
6+
public void Stop();
7+
8+
public string GetDiagnosticsName();
9+
public string? GetDiagnosticsInfo();
10+
}

0 commit comments

Comments
 (0)