(Make sure to tell msgpack to use the bin type - that way, the raw type can be parsed as a Unicode string.)
All packets:
{
// This string is equal to the object name listed in this protocol. It is used to identify the type of packet.
id: string
[..and then the rest follows..]
}
- Client connects. (TCP SYN)
- Server waits for any client message (~5 seconds)
- We don't want server to send server status to any connecting client as this is a big waste.
- Client sends ServerInfoRequest.
- Server sends back ServerInfoResponse.
- Client sends JoinRequest.
- Server sends JoinResponse.
- Client sends AssetListRequest.
- Server sends AssetListResponse.
- Note: any assets that are transferred directly from server to client are done on a different band, such as HTTP.
ServerInfoRequest:
{
type: enum {
// Player count, used by MS
PING = 0
// Server responds with ServerInfoResponse.
// (Useful when populating server list, since only basic info is needed.)
BASIC = 1
// Server responds with ServerInfoResponse but with some extra stuff.
// (Useful when client is getting detailed info about a server.)
FULL = 2
}
}
ServerInfoResponse:
{
name: string
address: string
port: uint16
version: string
player_count: uint32
max_players: uint32
protection: enum {
// No password is needed to join a room.
OPEN = 0
// Joining the server itself requires a password.
JOIN_WITH_PASSWORD = 1
// Joining the server is possible, but only spectating
// is open. (Password may be needed to join a room.)
SPECTATE_ONLY = 2
// Server is enforcing a whitelist.
WHITELIST = 3
// Server is not open to any new players or spectators.
CLOSED = 4
}
(details: object {
// Applicable only if password-protected
(auth_challenge: bytes)
desc: string
players: array of player {
name: string
character_name: string
join_time: uint32
}
})
}
JoinRequest:
{
player_name: string
// If trying to join with password: sha256(auth_challenge + password)
(auth_response: bytes)
player_id: string
}
JoinResponse:
{
result_code: enum {
SUCCESS = 0
SERVER_FULL = 1
BAD_PASSWORD = 2
BANNED = 3
OTHER = 4
}
result_msg: string
}
RoomListRequest:
{
empty
}
RoomListResponse:
{
rooms: [room {
id: uint32
name: string
(desc: string)
players: uint32
(players_max: uint32)
}
}
JoinRoomRequest:
{
room_id: uint32
char_id: uint32
(password: string)
}
JoinRoomResponse:
{
result: enum {
SUCCESS = 0
ROOM_FULL = 1
BAD_PASSWORD = 2
}
room_state: {
background: string
audio: string
audio_start: uint64 (Unix timestamp)
last_event: ChatMessage
last_event_time: uint64 (Unix timestamp)
}
}