Scopa Online Multiplayer Protocol

This page contains an example of communication between the server and a client. These JSON messages must be exchanged though a WebSocket.

Registration

client → server

New user registration request:

{
    "control": "register",
    "data": {
        "username": "john",
        "password": "verystrongpassword"
    }
}

client ← server

Response to a registration request if the desired username is anavailable:

{
    "control": "username_unavailable",
    "data": "john"
}

Response to a registration request if the registration was successful:

{
    "control": "registered",
    "data": "john"
}

Login

client → server

Login request:

{
    "control": "login",
    "data": {
        "username": "john",
        "password": "verystrongpassword"
    }
}

client ← server

Response to a login request if the given password is wrong:

{
    "control": "wrong_password",
    "data": "john"
}

Response to a login request if the given username does not exists on the server:

{
    "control": "unknown_username",
    "data": "john"
}

Response to a login request if the login is successful:

{
    "control": "logged_in",
    "data": {
        "username": "john",
        "games": {
            "classic_scopa": {"name": "Classic Scopa", "number_of_players": [2,4]},
            "cirulla": {"name": "Cirulla", "number_of_players": [2,4]}
        }
    }
}

client ← server (broadcast)

List of players registered on the server and their statuses (sent each time a player connects or disconnects):

{
    "control": "players",
    "data": [
        {"username": "john", "status": "available"},
        {"username": "mark", "status": "busy"},
        {"username": "mike", "status": "offline"},
        ...
    ]
}

Match negotiation

client → server

New match request:

{
    "control": "new_match",
    "data": {
        "game": "cirulla",
        "teams": [
            [
                {"name": "john", "type": "human"},
                {"name": "cpu1", "type": "cpu"},
            ],
            [
                {"name": "mike", "type": "human"},
                {"name": "cpu2", "type": "cpu"},
            ]
        ]
    }
}

client ← server (to other human players of the match)

Match proposal to other players:

{
    "control": "match_proposal",
    "data": {
        "game": "cirulla",
        "teams": [
            [
                {"name": "john", "type": "human"},
                {"name": "cpu1", "type": "cpu"},
            ],
            [
                {"name": "mike", "type": "human"},
                {"name": "cpu2", "type": "cpu"},
            ]
        ]
    }
}

client → server

Affirmative response to a match proposal:

{
    "control": "match_proposal",
    "data": "accept"
}

Negative response to a match proposal:

{
    "control": "match_proposal",
    "data": "refuse"
}

client ← server (to all human players of the match)

The match failed because one player refused to play:

{
    "control": "player_refused",
    "data": "mike"
}

The match will start after this message:

{
    "control": "match_started",
    "data": null
}

Match

client ← server (to all human players of the match)

Scopa Game Protocol message:

{
    "control": "match_data",
    "data": {...}
}

client → server

Scopa Game Protocol message:

{
    "control": "match_data",
    "data": {...}
}

client → server

Chat message:

{
    "control": "chat",
    "data": "Nice move!"
}

client ← server (to all human players of the match)

Chat message:

{
    "control": "chat",
    "data": {
        "player": "mike",
        "message": "Nice move!",
        "date": "2016-08-27T16:10:24.553Z"
    }
}

...

client ← server (to all human players of the match)

Scopa Game Protocol message (match end):

{
    "control": "match_data",
    "data": {
        "infos": [{"info": "winner", "data": ["john"]}],
        "moves": [],
        "cards": []
    }
}

client ← server (to all human players of the match)

Match end message:

{
    "control": "match_end",
    "data": null
}