Ignore leave events for spectators.

Spectators produce leave events, but they won't have a join event that
matches the leave event they produce. This is because spectators either
joined _as_ spectators (spectating doesn't produce join events), or they
_transitioned_ into the spectator state after _dying_ in the session (in
which case they already produced a death event that "cements" the player
session).

This fixes an edge case problem that occurs when a spectator produces a
leave event while exactly one player is currently in the lobby. In this
case, the leave event triggers a session deletion, since the leave event
logic "thinks" the leave event is triggered by the player in the lobby.
It would be possible to prevent that problem with additional checks in
the leave event logic, but the underlying problem really is that leave
events produced by spectators shouldn't be recorded or reacted to in any
way, shape, or form, as they are not relevant to the stats (leave times
are only really relevant if the leave event happens _during_ a session,
which this change does not affect).
This commit is contained in:
Andreas Troelsen
2022-07-25 17:30:19 +02:00
parent 85df0066f1
commit 9e92094501
2 changed files with 21 additions and 0 deletions
@@ -88,6 +88,10 @@ public class SessionListener implements Listener {
Arena arena = event.getArena();
Player player = event.getPlayer();
if (arena.inSpec(player)) {
return;
}
Session session = sessionStore.getByArena(arena);
if (session == null) {
log.warning("Unexpected leave event for non-existent session of arena " + arena.getSlug());
@@ -110,10 +110,23 @@ class SessionListenerTest {
verify(session).playerReady(player, className);
}
@Test
void ignoresPlayerLeaveForSpectators() {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
when(arena.inSpec(player)).thenReturn(true);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
subject.on(event);
verifyNoInteractions(sessionStore);
}
@Test
void logsWarningIfPlayerLeavesInNonExistentSession() {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
when(arena.inSpec(player)).thenReturn(false);
when(sessionStore.getByArena(arena)).thenReturn(null);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);
@@ -127,6 +140,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -142,6 +156,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(Collections.singleton(player));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -158,6 +173,7 @@ class SessionListenerTest {
Player other = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(false);
when(arena.getPlayersInLobby()).thenReturn(new HashSet<>(Arrays.asList(player, other)));
when(sessionStore.getByArena(arena)).thenReturn(session);
@@ -173,6 +189,7 @@ class SessionListenerTest {
Player player = mock(Player.class);
Arena arena = mock(Arena.class);
Session session = mock(Session.class);
when(arena.inSpec(player)).thenReturn(false);
when(arena.isRunning()).thenReturn(true);
when(sessionStore.getByArena(arena)).thenReturn(session);
ArenaPlayerLeaveEvent event = new ArenaPlayerLeaveEvent(player, arena);