Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(messaging): game join failed command #1045

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
32 changes: 29 additions & 3 deletions server/lobbyconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@
from .rating import InclusiveRange, RatingType
from .rating_service import RatingService
from .types import Address, GameLaunchOptions
from .version_util import is_version_less_or_equal_than


@with_logger
class LobbyConnection:
CLIENT_VERSION_NOTICE_COMPATIBLE = "2025.1.0"

@timed()
def __init__(
self,
Expand Down Expand Up @@ -964,7 +967,12 @@
try:
game = self.game_service[uuid]
except KeyError:
await self.send({
await self.send_game_join_failed_response({
"command": "game_join_failed",
Ivan-Shaml marked this conversation as resolved.
Show resolved Hide resolved
"style": "info",
"text": "The host has left the game.",
"uid": uuid
}, {
"command": "notice",
"style": "info",
"text": "The host has left the game."
Expand All @@ -976,7 +984,12 @@

if not game or game.state is not GameState.LOBBY:
self._logger.debug("Game not in lobby state: %s state %s", game, game.state)
await self.send({
await self.send_game_join_failed_response({

Check warning on line 987 in server/lobbyconnection.py

View check run for this annotation

Codecov / codecov/patch

server/lobbyconnection.py#L987

Added line #L987 was not covered by tests
"command": "game_join_failed",
"style": "info",
"text": "The game you are trying to join is not ready.",
"uid": uuid
}, {
"command": "notice",
"style": "info",
"text": "The game you are trying to join is not ready."
Expand All @@ -987,7 +1000,12 @@
raise ClientError("The game cannot be joined in this way.")

if game.password != password:
await self.send({
await self.send_game_join_failed_response({
"command": "game_join_failed",
"style": "info",
"text": "Bad password (it's case sensitive).",
"uid": uuid
}, {
"command": "notice",
"style": "info",
"text": "Bad password (it's case sensitive)."
Expand All @@ -996,6 +1014,14 @@

await self.launch_game(game, is_host=False)

async def send_game_join_failed_response(self, new_message, legacy_message):
# For backwards compatibility
if is_version_less_or_equal_than(self.CLIENT_VERSION_NOTICE_COMPATIBLE,
self.version):
await self.send(legacy_message)
else:
await self.send(new_message)

@ice_only
async def command_game_matchmaking(self, message):
queue_name = str(
Expand Down
10 changes: 10 additions & 0 deletions server/version_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from packaging.version import Version


def is_version_less_or_equal_than(target_version_str, actual_version_str):
try:
target_version = Version(target_version_str)
actual_version = Version(actual_version_str)
return target_version >= actual_version
except Exception:
return False
27 changes: 27 additions & 0 deletions tests/unit_tests/test_lobbyconnection.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ async def test_command_game_join_without_password(
game_stats_service
):
lobbyconnection.send = mock.AsyncMock()
lobbyconnection.version = "2024.8.0"
lobbyconnection.game_service = game_service
game = mock.create_autospec(Game)
game.state = GameState.LOBBY
Expand Down Expand Up @@ -430,6 +431,7 @@ async def test_command_game_join_game_not_found(
):
lobbyconnection.send = mock.AsyncMock()
lobbyconnection.game_service = game_service
lobbyconnection.version = "2024.8.0"
lobbyconnection.player = players.joining
players.joining.state = PlayerState.IDLE
test_game_info["uid"] = 42
Expand All @@ -445,6 +447,31 @@ async def test_command_game_join_game_not_found(
})


async def test_command_game_join_game_not_found_higher_version(
lobbyconnection,
game_service,
test_game_info,
players
):
lobbyconnection.send = mock.AsyncMock()
lobbyconnection.game_service = game_service
lobbyconnection.version = "2025.2.0"
lobbyconnection.player = players.joining
players.joining.state = PlayerState.IDLE
test_game_info["uid"] = 42

await lobbyconnection.on_message_received({
"command": "game_join",
**test_game_info
})
lobbyconnection.send.assert_called_once_with({
"command": "game_join_failed",
"style": "info",
"text": "The host has left the game.",
"uid": 42
})


async def test_command_game_join_game_bad_init_mode(
lobbyconnection,
game_service,
Expand Down
29 changes: 29 additions & 0 deletions tests/unit_tests/test_version_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import unittest

from server.version_util import is_version_less_or_equal_than


class TestVersionComparison(unittest.TestCase):

def test_valid_version_comparisons(self):
# Test valid version comparisons
self.assertTrue(is_version_less_or_equal_than("2024.6.0-alpha-1", "2024.6.0-alpha-0"))
self.assertTrue(is_version_less_or_equal_than("2024.6.0-alpha-1", "2024.6.0-alpha-1"))
self.assertFalse(is_version_less_or_equal_than("2024.6.0-alpha-0", "2024.6.0-alpha-1"))
self.assertTrue(is_version_less_or_equal_than("2025.3.0", "2025.1.0"))
self.assertFalse(is_version_less_or_equal_than("2025.1.0", "2025.3.0"))
self.assertTrue(is_version_less_or_equal_than("2025.1.0", "2025.1.0-alpha-1"))
self.assertTrue(is_version_less_or_equal_than("2025.1.0", "1.0.0"))

def test_invalid_version_strings(self):
# Test invalid version strings
self.assertFalse(is_version_less_or_equal_than("2024-6-0-alpha-1", "2024.6.0-alpha-0"))
self.assertFalse(is_version_less_or_equal_than("2024.6.0-alpha-1", "2024-6-0-alpha-0"))
self.assertTrue(is_version_less_or_equal_than("v2024.6.0-alpha-1", "2024.6.0-alpha-0"))
self.assertTrue(is_version_less_or_equal_than("2024.6.0-alpha-1", "v2024.6.0-alpha-0"))

def test_edge_cases(self):
# Test edge cases
self.assertFalse(is_version_less_or_equal_than(None, "2024.6.0-alpha-0"))
self.assertFalse(is_version_less_or_equal_than("2024.6.0-alpha-1", None))
self.assertFalse(is_version_less_or_equal_than(None, None))
Loading