Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions server/gameconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ async def _handle_idle_state(self):
"""
assert self.game

if self.state is not GameConnectionState.INITIALIZING:
self._logger.warning(
"Ignoring unexpected 'Idle' state when state was %s",
self.state,
)
return

if self.player == self.game.host:
self.game.state = GameState.LOBBY
self._state = GameConnectionState.CONNECTED_TO_HOST
Expand All @@ -132,6 +139,13 @@ async def _handle_lobby_state(self):
"""
player_state = self.player.state
if player_state == PlayerState.HOSTING:
if self.game.hosted_at is not None:
self._logger.warning(
"Ignoring unexpected 'Lobby' state sent when the game was "
"already hosted.",
)
return

await self.send_HostGame(self.game.map.folder_name)
self.game.set_hosted()
# If the player is joining, we connect him to host
Expand Down
42 changes: 42 additions & 0 deletions tests/integration_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,48 @@ async def test_ladder_game_not_joinable(lobby_server):
}


@fast_forward(60)
async def test_gamestate_lobby_double_game_instance(lobby_server):
"""There was a bug in the client that was causing multiple game instances
to launch simultaneously. This could cause the GpgNet messages in the game
startup sequence to be sent twice.
"""
_, _, host_proto = await connect_and_sign_in(
("test", "test_password"), lobby_server
)
_, _, guest_proto = await connect_and_sign_in(
("Rhiza", "puff_the_magic_dragon"), lobby_server
)
await read_until_command(host_proto, "game_info")
await read_until_command(guest_proto, "game_info")

await host_proto.send_message({
"command": "game_host",
"mod": "faf",
"visibility": "public",
})
msg = await read_until_command(host_proto, "game_launch")
game_id = int(msg["uid"])

for _ in range(2):
await host_proto.send_message({
"target": "game",
"command": "GameState",
"args": ["Idle"]
})

for _ in range(2):
await host_proto.send_message({
"target": "game",
"command": "GameState",
"args": ["Lobby"]
})

await read_until_command(host_proto, "HostGame", target="game")

await join_game(guest_proto, game_id)


@pytest.mark.flaky
@fast_forward(60)
async def test_gamestate_ended_clears_references(
Expand Down
21 changes: 18 additions & 3 deletions tests/unit_tests/test_gameconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,33 @@
await game_connection.connect_to_peer(peer)


async def test_handle_action_GameState_idle_adds_connection(
async def test_handle_action_GameState_idle_hosting(
game: Game,
game_connection: GameConnection,
players
):
players.joining.game = game
game_connection.player = players.hosting
game_connection.game = game

await game_connection.handle_action("GameState", ["Idle"])

game.add_game_connection.assert_called_with(game_connection)
game.add_game_connection.assert_called_once_with(game_connection)


async def test_handle_action_GameState_idle_joining(
game: Game,
game_connection: GameConnection,
players
):
game_connection.player = players.joining
game_connection.game = game

await game_connection.handle_action("GameState", ["Idle"])

assert players.joining.state == PlayerState.JOINING
assert game_connection.state == GameConnectionState.INITIALIZED

game.add_game_connection.assert_not_called()


async def test_handle_action_GameState_idle_sets_player_state(
Expand All @@ -131,7 +146,7 @@

await game_connection.handle_action("GameState", ["Idle"])

assert players.joining.state == PlayerState.JOINING

Check failure on line 149 in tests/unit_tests/test_gameconnection.py

View workflow job for this annotation

GitHub Actions / unit-test

test_handle_action_GameState_idle_sets_player_state AssertionError: assert <PlayerState.IDLE: 1> == <PlayerState.JOINING: 4> + where <PlayerState.IDLE: 1> = Player(login=James_Kirk, session=0, id=3, ratings={'global': Rating(mean=1500, dev=500), 'ladder_1v1': Rating(mean=1500, dev=500)}, clan=None, game_count={'global': 0, 'ladder_1v1': 0}).state + where Player(login=James_Kirk, session=0, id=3, ratings={'global': Rating(mean=1500, dev=500), 'ladder_1v1': Rating(mean=1500, dev=500)}, clan=None, game_count={'global': 0, 'ladder_1v1': 0}) = <Mock id='140380429953264'>.joining + and <PlayerState.JOINING: 4> = PlayerState.JOINING


async def test_handle_action_GameState_lobby_sends_HostGame(
Expand All @@ -145,7 +160,7 @@
await game_connection.handle_action("GameState", ["Lobby"])
await exhaust_callbacks()

assert_message_sent(game_connection, "HostGame", [game.map.folder_name])

Check failure on line 163 in tests/unit_tests/test_gameconnection.py

View workflow job for this annotation

GitHub Actions / unit-test

test_handle_action_GameState_lobby_sends_HostGame AssertionError: expected call not found. Expected: send_message({'command': 'HostGame', 'target': 'game', 'args': ['some_map']}) Actual: not called.


async def test_handle_action_GameState_lobby_calls_ConnectToHost(
Expand Down
Loading