Skip to content

Commit

Permalink
#66 Kick client if server leaves/crashes.
Browse files Browse the repository at this point in the history
Current implementation does not distinguish between server leave and crash.
  • Loading branch information
zuev93 committed Oct 18, 2023
1 parent 6f69e5a commit 85f65d9
Show file tree
Hide file tree
Showing 11 changed files with 66 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private static void PlayerConnectedAndDisconnected(bool gracefully) {
clientRuntime.Activate();

if (gracefully) {
clientRuntime.EventDispatcher().Dispatch(new GameQuitEvent(clientRuntime.Multiplayer()));
clientRuntime.EventDispatcher().Dispatch(new GameQuitEvent());
Assert.AreEqual(expected: 0, clientRuntime.Multiplayer().Players.Count());
} else {
clientRuntime.Dependencies.Get<IMultiplayerClient>().Disconnect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private void Bind() {
log.Debug("Binding host events");

eventDispatcher.Subscribe<GameStartedEvent>(OnGameStarted);
eventDispatcher.Subscribe<GameQuitEvent>(OnGameQuit);
eventDispatcher.Subscribe<StopMultiplayerEvent>(OnStopMultiplayer);

ChoreConsumerEvents.FindNextChore += p => server.Send(new FindNextChore(p), MultiplayerCommandOptions.SkipHost);
}
Expand All @@ -51,7 +51,7 @@ private void OnGameStarted(GameStartedEvent @event) {
};
}

private void OnGameQuit(GameQuitEvent @event) {
private void OnStopMultiplayer(StopMultiplayerEvent @event) {
if (@event.Multiplayer.Mode != MultiplayerMode.Host)
return;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using MultiplayerMod.Core.Events;

namespace MultiplayerMod.Multiplayer.CoreOperations.Events;

public record ConnectionLostEvent : IDispatchableEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

namespace MultiplayerMod.Multiplayer.CoreOperations.Events;

public record GameQuitEvent(MultiplayerGame Multiplayer) : IDispatchableEvent;
public record GameQuitEvent : IDispatchableEvent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using MultiplayerMod.Core.Events;

namespace MultiplayerMod.Multiplayer.CoreOperations.Events;

public record StopMultiplayerEvent(MultiplayerGame Multiplayer) : IDispatchableEvent;
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ MultiplayerGame multiplayer
eventDispatcher.Subscribe<SinglePlayerModeSelectedEvent>(OnSinglePlayerModeSelected);
eventDispatcher.Subscribe<MultiplayerModeSelectedEvent>(OnMultiplayerModeSelected);
eventDispatcher.Subscribe<PlayerStateChangedEvent>(OnPlayerStateChangedEvent);
eventDispatcher.Subscribe<GameQuitEvent>(OnGameQuit);
eventDispatcher.Subscribe<StopMultiplayerEvent>(OnStopMultiplayer);
}

private void OnSinglePlayerModeSelected(SinglePlayerModeSelectedEvent @event) {
Expand All @@ -41,7 +41,7 @@ private void OnPlayerStateChangedEvent(PlayerStateChangedEvent @event) {
executionLevelManager.BaseLevel = ExecutionLevel.Game;
}

private void OnGameQuit(GameQuitEvent _) {
private void OnStopMultiplayer(StopMultiplayerEvent _) {
executionLevelManager.BaseLevel = ExecutionLevel.System;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public GameStateEventsRelay(EventDispatcher events, MultiplayerGame multiplayer,

private void OnWorldSave() => events.Dispatch(new WorldSavedEvent());

private void OnGameQuit() => events.Dispatch(new GameQuitEvent(multiplayer));
private void OnGameQuit() => events.Dispatch(new GameQuitEvent());

private void OnGameStarted() => scheduler.Run(() => events.Dispatch(new GameStartedEvent(multiplayer)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public MultiplayerServerController(IMultiplayerServer server, IMultiplayerClient
this.events = events;

events.Subscribe<GameStartedEvent>(OnGameStarted);
events.Subscribe<GameQuitEvent>(OnGameQuit);
events.Subscribe<StopMultiplayerEvent>(OnStopMultiplayer);

server.StateChanged += OnServerStateChanged;
}
Expand All @@ -46,7 +46,7 @@ private void OnGameStarted(GameStartedEvent @event) {
server.Start();
}

private void OnGameQuit(GameQuitEvent @event) {
private void OnStopMultiplayer(StopMultiplayerEvent @event) {
if (@event.Multiplayer.Mode != MultiplayerMode.Host)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class PlayersManagementController {
private readonly IMultiplayerServer server;
private readonly IMultiplayerClient client;

private readonly EventDispatcher events;

private readonly WorldManager worldManager;
private readonly MultiplayerGame multiplayer;
private readonly UnityTaskScheduler scheduler;
Expand All @@ -39,19 +41,21 @@ public PlayersManagementController(
MultiplayerGame multiplayer,
UnityTaskScheduler scheduler
) {
this.client = client;
this.profileProvider = profileProvider;
this.server = server;
this.client = client;
this.events = events;
this.worldManager = worldManager;
this.multiplayer = multiplayer;
this.scheduler = scheduler;
this.profileProvider = profileProvider;

server.ClientDisconnected += OnClientDisconnected;
events.Subscribe<ClientInitializationRequestEvent>(OnClientInitializationRequested);

client.StateChanged += OnClientStateChanged;
events.Subscribe<GameStartedEvent>(OnGameStarted);
events.Subscribe<GameQuitEvent>(OnGameQuit);
events.Subscribe<StopMultiplayerEvent>(OnStopMultiplayer);
events.Subscribe<CurrentPlayerInitializedEvent>(OnCurrentPlayerInitialized);
events.Subscribe<WorldSyncRequestedEvent>(OnWorldSaveRequested);
}
Expand All @@ -65,10 +69,12 @@ private void OnCurrentPlayerInitialized(CurrentPlayerInitializedEvent @event) {
}

private void OnClientStateChanged(MultiplayerClientState state) {
if (state != MultiplayerClientState.Connected)
return;

client.Send(new InitializeClientCommand(profileProvider.GetPlayerProfile()));
if (state == MultiplayerClientState.Connected)
client.Send(new InitializeClientCommand(profileProvider.GetPlayerProfile()));
if (state == MultiplayerClientState.Error) {
events.Dispatch(new StopMultiplayerEvent(multiplayer));
events.Dispatch(new ConnectionLostEvent());
}
}

private void OnGameStarted(GameStartedEvent @event) {
Expand All @@ -81,6 +87,10 @@ private void OnGameStarted(GameStartedEvent @event) {

private void OnGameQuit(GameQuitEvent @event) {
client.Send(new RequestPlayerStateChangeCommand(multiplayer.Players.Current.Id, PlayerState.Leaving));
events.Dispatch(new StopMultiplayerEvent(multiplayer));
}

private void OnStopMultiplayer(StopMultiplayerEvent @event) {
client.Disconnect();
multiplayer.Players.Synchronize(Array.Empty<MultiplayerPlayer>());
}
Expand Down
27 changes: 27 additions & 0 deletions src/MultiplayerMod/Multiplayer/UI/Notifications.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using JetBrains.Annotations;
using MultiplayerMod.Core.Dependency;
using MultiplayerMod.Core.Events;
using MultiplayerMod.Multiplayer.CoreOperations.Events;

namespace MultiplayerMod.Multiplayer.UI;

[Dependency, UsedImplicitly]
public class Notifications {

public Notifications(EventDispatcher events) {
events.Subscribe<ConnectionLostEvent>(OnConnectionLost);
}

private void OnConnectionLost(ConnectionLostEvent @event) {
var screen = (InfoDialogScreen) GameScreenManager.Instance.StartScreen(
ScreenPrefabs.Instance.InfoDialogScreen.gameObject,
GameScreenManager.Instance.ssOverlayCanvas.gameObject
);
screen.SetHeader("Multiplayer");
screen.AddPlainText("Connection has been lost. Further play can not be synced");
screen.AddOption(
"OK",
_ => PauseScreen.Instance.OnQuitConfirm()
);
}
}
6 changes: 4 additions & 2 deletions src/MultiplayerMod/Platform/Steam/Network/SteamClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public void Connect(IMultiplayerEndpoint endpoint) {
}

public void Disconnect() {
if (State <= MultiplayerClientState.Disconnected)
if (State == MultiplayerClientState.Disconnected)
throw new NetworkPlatformException("Client not connected");

UnityObject.Destroy(gameObject);
Expand Down Expand Up @@ -96,8 +96,10 @@ public void Send(IMultiplayerCommand command, MultiplayerCommandOptions options
k_nSteamNetworkingSend_Reliable,
out var messageOut
);
if (result != EResult.k_EResultOK && messageOut == 0)
if (result != EResult.k_EResultOK || messageOut == 0) {
log.Error($"Failed to send {command}: {result}");
SetState(MultiplayerClientState.Error);
}
}
);
}
Expand Down

0 comments on commit 85f65d9

Please sign in to comment.