190 lines
5.8 KiB
Markdown
190 lines
5.8 KiB
Markdown
|
|
# Communication
|
|
|
|
OUTDATED!
|
|
This documentation is outdated.
|
|
Some of the messages have changed, and more messages have been added.
|
|
|
|
This document is to descrive how the communication between the server and the client currently works.
|
|
|
|
There may be better ways and it may be subject to change, but this works now.
|
|
|
|
## packets over TCP
|
|
|
|
The communication happens over a TCP Unix Domain Socket, by default an abstract UDS.
|
|
|
|
In order to send discrete messages (instead of just a stream of bytes) over TCP the message is prefixed by a header of 4 bytes defining the length of the message in big endian notation.
|
|
This length is the length of the message body, the header is not included
|
|
Both server and client use tcommunicate.py to achieve this.
|
|
|
|
|
|
## JSON data
|
|
|
|
The message body is JSON text
|
|
|
|
The top-level JSON value is a message or a list of messages.
|
|
|
|
A message is a list, where the first element is a string defining the message type.
|
|
|
|
For example, the whole message could look like this:
|
|
|
|
[
|
|
["health", 85],
|
|
["inventory", ["seed"]]
|
|
]
|
|
|
|
|
|
|
|
## Client to server messages
|
|
|
|
Currently there are three types of messages that the client can send to the server: 'name', 'input' and 'chat'
|
|
|
|
### 'name' messages
|
|
|
|
The 'name' message is used to pick the name of a player to connect to.
|
|
The value of this message is a single string.
|
|
This message must be sent before any other communication.
|
|
|
|
Example message: `["name", "troido"]`
|
|
|
|
If a player with that name did not exist yet, it will be created and the connection will be connected that player.
|
|
|
|
If a player with that name does exist, but it no other connection is currenty connected to that player, the connection will be connected to that player too.
|
|
|
|
Once the connection is connected to a player it will put the player in the game and send its view to the player
|
|
|
|
If another connection is already connected to a player with that name, the server will send an error message and ignore all communication until the next 'name' message.
|
|
|
|
### 'input' messages
|
|
|
|
'input' messages are sent to control the player.
|
|
If the connection is not connected to any player, these messages are ignored.
|
|
The value of this message is a list with a length of at least 1.
|
|
The first item in the list is the type of command, later items are arguments
|
|
|
|
Example message: `["input", ["move", "east"]]`
|
|
|
|
### 'chat' messages
|
|
|
|
'chat' messages are used to send messages to all connections, without going through the world first.
|
|
|
|
The value of this message is the string to send.
|
|
This string may only contain printable characters.
|
|
|
|
Example message: `["chat", "hello, other asciifarm players"]`
|
|
|
|
## Server to client messages
|
|
|
|
There are several types of messages that the server can send to the client: 'field', 'inventory', 'health', 'ground' and 'error'
|
|
|
|
Currently, 'chanchedcells' and 'info' messages are always sent in the same dictionary.
|
|
If there is a 'field' message, it will also be sent in that dictionary.
|
|
|
|
### 'error' messages
|
|
|
|
'error' messages are sent when a player tries to connect with a name that is already connected or when the input is wrong.
|
|
Wrong input is not always guaranteed to give an error message.
|
|
The first value is a string to give the type of error.
|
|
The message may have more data to explain the error.
|
|
|
|
Example message: `["error", "nametaken"]`
|
|
|
|
|
|
### 'field' messages
|
|
|
|
'field' messages send the full visible state of the room
|
|
It has the following properties:
|
|
|
|
- width: the width of the room
|
|
- height: the height of the room
|
|
- field: a 1 dimensional array (length: width*height) of integers representing the sprites in all cells of the room.
|
|
- mapping: an array or dictionary of spritenames. The values in field are the indices for the mapping.
|
|
|
|
Only one sprite per cell is sent: the one with the largest height.
|
|
|
|
Example message:
|
|
|
|
["field", {
|
|
"width": 3,
|
|
"height": 3,
|
|
"field": [0,0,1,0,0,2,1,0,0],
|
|
"mapping": ["grass", "stone", "player"]
|
|
}]
|
|
|
|
When the character for grass is ',', for stone is 'o' and for player is '@', then this message would correspond to the field:
|
|
|
|
,,o
|
|
,,@
|
|
o,,
|
|
|
|
See view.py and Grid.toDict in grid.py for the implementation.
|
|
|
|
### 'changecells' messages
|
|
|
|
'changecells' messages update the visible state of some of the cells on the screen.
|
|
The data is a list of cells.
|
|
A cell is a list of two elements: first the position and then the spritename
|
|
The position is also a list of 2 elements: first the x, position and then the y.
|
|
|
|
Example message:
|
|
|
|
["changecells", [
|
|
[[1, 2], "grass],
|
|
[[2, 2], "player"]
|
|
]]
|
|
|
|
### 'health' messages
|
|
|
|
'health' messages send the health of the player.
|
|
|
|
Example `["health", 96]`
|
|
|
|
|
|
### 'inventory' messages
|
|
|
|
'inventory' messages send the inventory of the player.
|
|
|
|
Example `["inventory", ["stone", "seed", "food"]]`
|
|
|
|
|
|
### 'ground' messages
|
|
|
|
'ground' messages send the objects that are on the same square as the player (excluding the player themselves).
|
|
|
|
Example `["ground", ["stone", "seed", "ground"]]`
|
|
|
|
|
|
# Suggested improvements
|
|
|
|
## [DONE] Human readable error messages
|
|
|
|
DONE
|
|
|
|
Currently error messages only have a computer readable string.
|
|
|
|
It would be nice if it could sent a human readable string too.
|
|
|
|
This has low priority and is only useful once the client has some console to print to.
|
|
|
|
|
|
|
|
## [DONE] Lists as outer objects
|
|
|
|
DONE
|
|
|
|
Currently all messages are dictionaries, which results in nonintuitive code where the key determines the type of the message, and where unrelated messages can be send in the same message.
|
|
|
|
A solution would be to send lists as outer objects where the first element of the list is the type of message.
|
|
|
|
Example: `["input", ["move", "north"]]`
|
|
|
|
## [DONE] partial field update
|
|
|
|
DONE
|
|
|
|
Sending the complete field each update is very costly for both the client and the server
|
|
|
|
A solution would be to send a list of areas to be updated (after the player has entered the room initially).
|
|
|
|
Another solution is to send a list of single cells to be updated.
|