-
Notifications
You must be signed in to change notification settings - Fork 33
The CloudLink Protocol
Work in progress!
This page outlines CLPv4.1. Packets within CLPv4.1 are compliant with UPLv2.2.
UPLv2.2 is a formatting scheme that simplifies the protocol, and has existed since CLPv3.
In short, each packet that is UPL compliant is a JSON encoded text frame.
Each JSON message will have no more than these root keys:
{
"cmd": String, // Required for all commands, The CL Protocol command to execute.
"val": [ // Command-specific. Not required for some commands.
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
],
"mode": String, // Only used for server to client ulist command
"name": String, // Required for variable-related commands.
"id": String, // Required for direct or private message commands.
"relay": String, // Optional, same as id, but will relay the entire packet instead. Will only work on servers 0.2.0 or newer.
"listener": String // Optional, attach to message to get a response.
"rooms": [ // Optional for client to server messages, required for server to client messages if a client is linked to rooms
String,
List // List of strings
],
"origin": Object, // User object of originating client, only used with private messages or the direct command.
"details": String // For error messages only. It's value is a description of what went wrong and how to fix the error.
}
When a client connects to a CloudLink server, it is recommended that the first message to be sent client to server is the handshake
command.
Request
{
"cmd": "handshake",
"listener": String // Optional
}
Responses
- The server will return the detected IP address of the client.
{
"cmd": "client_ip",
"val": String
}
- The server will report what version it's running.
{
"cmd": "server_version",
"val": String
}
- If enabled, the server will provide its "Message of the Day".
{
"cmd": "motd",
"val": String
}
- The server will provide the client it's user object info.
{
"cmd": "client_obj",
"val": {
"id": String, // Snowflake ID
"uuid": String // UUID
}
}
- The server will report the current userlist of the
default
room.
{
"cmd": "ulist",
"mode": "set",
"val": [], // List of user objects, following the same format as client_obj
"rooms": "default"
}
- The server will return a status code (and a listener, if specified).
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
Afterwards, the client does not need to send the handshake
command during the remainder of the websocket connection.
This command broadcasts a message to everyone in your currently linked rooms (defaults to a single room: "default").
Request
{
"cmd": "gmsg",
"val": [ // Whatever you would like to broadcast
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
Responses
If you specified a listener in your message, the server will broadcast this message to all clients (excluding yours):
{
"cmd": "gmsg",
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
}
Afterwards, it will return with the same message with your listener.
{
"cmd": "gmsg",
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
Object, // Dictionary in Python terms
Float
]
"listener": String
}
If you didn't specify a listener in your message, you will receive the exact same message as every other client.
This command broadcasts a variable to everyone in your currently linked rooms (defaults to a single room: "default").
Request
{
"cmd": "gvar",
"name": String // Variable name
"val": [ // Whatever you would like to broadcast
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
Responses
If you specified a listener in your message, the server will broadcast this message to all clients (excluding yours):
{
"cmd": "gvar",
"name": String // Variable name
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
}
Afterwards, it will return with the same message with your listener.
{
"cmd": "gvar",
"name": String // Variable name
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
If you didn't specify a listener in your message, you will receive the exact same message as every other client.
Before you can utilize link
, unlink
, pmsg
, pvar
, direct
, or relay
commands, you will need to set a username for your client.
Request
{
"cmd": "setid",
"val": String // Username,
"listener": String // Optional
}
Response
- The server will broadcast a
ulist add
command to other clients. This message does not get sent to your client.
{
"cmd": "ulist",
"mode": "add",
"val": {
"id": String, // Your Snowflake ID
"username": String, // Your Username
"uuid": String // Your UUID
},
"rooms": "default"
}
- The server will return to you with a
ulist set
command.
{
"cmd": "ulist",
"mode": "set",
"val": [] // List of user objects, which will include your updated user object
"rooms": "default"
}
- The server will return a status code (and a listener, if specified).
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
pmsg
is similar to gmsg
, but it allows you to send a message to a specific client, or a series of clients. This comes with security and speed benefits. Unlike direct
, this message respects rooms, and requires your recipient(s) to be in the same room(s) as your client.
For any private command, you can specify a single string username/snowflake ID/UUID to select a client. You can also specify a list of string usernames/snowflake IDs/UUIDs. For compatibility between differing server languages, it is suggested to specify a user object instead.
Request
{
"cmd": "pmsg",
"id": [
String, // Username/Snowflake ID/UUID of the client to send to
Object, // Complete user object
List // Collection of Strings or User Objects
],
"val": [ // Whatever you would like to broadcast
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
Response
- Each recipient will receive your message excluding a listener. It will include the
origin
key containing a copy of your client's user object.
{
"cmd": "pmsg",
"origin": Object, // Your client object
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
pvar
is similar to gvar
, but it allows you to send a variable to a specific client, or a series of clients. This comes with security and speed benefits. Unlike direct
, this message respects rooms, and requires your recipient(s) to be in the same room(s) as your client.
For any private command, you can specify a single string username/snowflake ID/UUID to select a client. You can also specify a list of string usernames/snowflake IDs/UUIDs. For compatibility between differing server languages, it is suggested to specify a user object instead.
Request
{
"cmd": "pvar",
"name": String, // Variable name
"id": [
String, // Username/Snowflake ID/UUID of the client to send to
Object, // Complete user object
List // Collection of Strings or User Objects
],
"val": [ // Whatever you would like to broadcast
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
Response
- Each recipient will receive your message excluding a listener. It will include the
origin
key containing a copy of your client's user object.
{
"cmd": "pvar",
"name": String, // Variable name
"origin": Object, // Your client object
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
This command is identical to pmsg
, however, it will send messages regardless of rooms. All that is required is that your message's recipient(s) must be connected during transit.
Request
{
"cmd": "direct",
"id": [
String, // Username/Snowflake ID/UUID of the client to send to
Object, // Complete user object
List // Collection of Strings or User Objects
],
"val": [ // Whatever you would like to broadcast
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
"listener": String // Optional
}
Response
- Each recipient will receive your message excluding a listener. It will include the
origin
key containing a copy of your client's user object.
{
"cmd": "direct",
"origin": Object, // Your client object
"val": [ // Whatever you broadcasted
String,
Integer,
Boolean,
List,
Object, // Dictionary in Python terms
Float
]
}
- Upon successful sending, the server will return to you with a statuscode.
{
"cmd": "statuscode",
"code": "I:100 | OK",
"code_id": 100,
"listener": String
}
{
"cmd": "statuscode",
"code": String, // Human readable error code (Also for compatibility with older CL projects)
"code_id": Integer, // Code #
"details": String // If the command specifies this key, this will provide a description of what went wrong, and how to fix your error.
}
Code # | Description |
---|---|
0 | Testing usage only. |
1 | Echo usage only. |
100 | The request has been processed successfully. |
101 | A syntax error has occurred. |
102 | A value in the request has an invalid/incompatible datatype. |
103 | The ID/IDs specified in the "id" key did not resolve any clients. |
104 | The ID/IDs specified in the "id" key found more than one result. Only occurs if the server is configured to warn about multiple matches. |
105 | Generic error message when the server encounters an internal error. See logs for details. |
106 | The server received an empty packet. |
107 | The client attempted to set it's username, but it's username was already set. |
108 | The server understood the request, but refused to process it. |
109 | The client sent an invalid command. |
110 | The client sent a command that was disabled. |
111 | The client attempted to use a command that requires setting a username. |
112 | A username conflict has occurred. |
113 | The client sent a request that was too large. |
114 | The client sent incorrectly formatted / corrupt JSON. |
115 | The client attempted to access a room that was not previously joined. |