Skip to content

Commit 2e12ff2

Browse files
authored
Fix for hosting an in-game server (#719)
* Minimal fix for hosting an in-game server * Further streamline server init data
1 parent 7fc6d20 commit 2e12ff2

File tree

5 files changed

+22
-22
lines changed

5 files changed

+22
-22
lines changed

Source/Client/Networking/HostUtil.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ private static void PrepareLocalServer(ServerSettings settings, bool fromReplay)
7474
localServer.startingTimer = TickPatch.Timer;
7575
}
7676

77-
localServer.initData =
78-
ServerInitData.Deserialize(new ByteReader(ClientJoiningState.PackInitData(settings.syncConfigs)));
77+
localServer.StartInitData().SetResult(
78+
ServerInitData.Deserialize(new ByteReader(ClientJoiningState.PackInitData(settings.syncConfigs))));
7979
}
8080

8181
private static void PrepareGame()

Source/Common/CommandHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ public void Send(CommandType cmd, int factionId, int mapId, byte[] data, ServerP
2020
{
2121
bool debugCmd =
2222
cmd == CommandType.DebugTools ||
23-
cmd == CommandType.Sync && server.initData!.DebugOnlySyncCmds.Contains(BitConverter.ToInt32(data, 0));
23+
cmd == CommandType.Sync && server.InitData!.DebugOnlySyncCmds.Contains(BitConverter.ToInt32(data, 0));
2424
if (debugCmd && !CanUseDevMode(sourcePlayer))
2525
return;
2626

27-
bool hostOnly = cmd == CommandType.Sync && server.initData!.HostOnlySyncCmds.Contains(BitConverter.ToInt32(data, 0));
27+
bool hostOnly = cmd == CommandType.Sync && server.InitData!.HostOnlySyncCmds.Contains(BitConverter.ToInt32(data, 0));
2828
if (hostOnly && !sourcePlayer.IsHost)
2929
return;
3030

Source/Common/MultiplayerServer.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ static MultiplayerServer()
4747
public ActionQueue queue = new();
4848
public ServerSettings settings;
4949

50-
public ServerInitData? initData;
50+
public ServerInitData? InitData => initDataSource.Task.ResultNowOrNull();
5151
private TaskCompletionSource<ServerInitData?> initDataSource = new();
5252
public InitDataState InitDataState =>
53-
initData != null ? InitDataState.Complete :
53+
InitData != null ? InitDataState.Complete :
5454
// started init data must've completed with null, meaning the client disconnected while waiting for the data,
5555
// so we are waiting again
5656
initDataSource.Task.IsCompleted ? InitDataState.Waiting :
@@ -250,22 +250,15 @@ public void RegisterChatCmd(string cmdName, ChatCmdHandler handler) =>
250250

251251
public void HandleChatCmd(IChatSource source, string cmd) => chatCmdManager.Handle(source, cmd);
252252

253-
public Task<ServerInitData?> InitData() => initDataSource.Task;
253+
public Task<ServerInitData?> InitDataTask() => initDataSource.Task;
254254

255255
/// Can only start one init data at a time. A StartInitData is considered complete once
256256
/// TaskCompletionResult.SetResult is called. Until that time no new calls to StartInitData will succeed.
257257
public TaskCompletionSource<ServerInitData?> StartInitData()
258258
{
259259
if (InitDataState != InitDataState.Waiting)
260260
throw new InvalidOperationException($"Can't start init data in state {InitDataState}");
261-
var currInitDataSource = initDataSource = new TaskCompletionSource<ServerInitData?>();
262-
currInitDataSource.Task.ContinueWith(task =>
263-
{
264-
if (currInitDataSource != initDataSource)
265-
ServerLog.Error("InitDataSource changed during StartInitData");
266-
initData = task.Result;
267-
}, TaskContinuationOptions.ExecuteSynchronously);
268-
return currInitDataSource;
261+
return initDataSource = new TaskCompletionSource<ServerInitData?>();
269262
}
270263
}
271264

Source/Common/Networking/State/ServerJoiningState.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Threading.Tasks;
1+
using System;
2+
using System.Threading.Tasks;
23

34
namespace Multiplayer.Common;
45

@@ -13,7 +14,7 @@ protected override async Task RunState()
1314
HandleProtocol(await Packet(Packets.Client_Protocol));
1415
HandleUsername(await Packet(Packets.Client_Username));
1516

16-
while (await Server.InitData() is null && await EndIfDead())
17+
while (await Server.InitDataTask() is null && await EndIfDead())
1718
if (Server.InitDataState == InitDataState.Waiting)
1819
await RequestInitData();
1920

@@ -105,9 +106,11 @@ private bool HandleClientJoinData(ByteReader data)
105106
var modCtorRoundMode = data.ReadEnum<RoundModeEnum>();
106107
var staticCtorRoundMode = data.ReadEnum<RoundModeEnum>();
107108

108-
if ((modCtorRoundMode, staticCtorRoundMode) != Server.initData!.RoundModes)
109+
var serverInitData = Server.InitData ??
110+
throw new Exception("Server init data is null during handling of client join data");
111+
if ((modCtorRoundMode, staticCtorRoundMode) != serverInitData.RoundModes)
109112
{
110-
Player.Disconnect($"FP round modes don't match: {(modCtorRoundMode, staticCtorRoundMode)} != {Server.initData!.RoundModes}");
113+
Player.Disconnect($"FP round modes don't match: {(modCtorRoundMode, staticCtorRoundMode)} != {serverInitData.RoundModes}");
111114
return false;
112115
}
113116

@@ -129,7 +132,7 @@ private bool HandleClientJoinData(ByteReader data)
129132

130133
var status = DefCheckStatus.Ok;
131134

132-
if (!Server.initData!.DefInfos.TryGetValue(defType, out DefInfo info))
135+
if (!serverInitData.DefInfos.TryGetValue(defType, out DefInfo info))
133136
status = DefCheckStatus.Not_Found;
134137
else if (info.count != defCount)
135138
status = DefCheckStatus.Count_Diff;
@@ -146,10 +149,10 @@ private bool HandleClientJoinData(ByteReader data)
146149
Packets.Server_JoinData,
147150
Server.settings.gameName,
148151
Player.id,
149-
Server.initData!.RwVersion,
152+
serverInitData.RwVersion,
150153
MpVersion.Version,
151154
defsResponse.ToArray(),
152-
Server.initData.RawData
155+
serverInitData.RawData
153156
);
154157

155158
return defsMatch;

Source/Common/Util/Extensions.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Reflection;
88
using System.Security.Cryptography;
99
using System.Text;
10+
using System.Threading.Tasks;
1011

1112
namespace Multiplayer.Common
1213
{
@@ -128,6 +129,9 @@ public static float MaxOrZero<T>(this IEnumerable<T> items, Func<T, float> map)
128129
{
129130
return items.Max(i => (float?)map(i)) ?? 0f;
130131
}
132+
133+
public static T? ResultNowOrNull<T>(this Task<T> task) where T : class? =>
134+
task.Status == TaskStatus.RanToCompletion ? task.Result : null;
131135
}
132136

133137
public static class Utils

0 commit comments

Comments
 (0)