lib/network.py
On the most basic level we wrap around QtNetwork.QTcpSocket, which can connect to and exchange bytes data remotely. In ExtendedTcPSocket we include such a socket and connect to its signals. We similarly wrap around QtNetwork.QTcpServer.
We read and write data through a QtCore.QDataStream that takes a QtCore.QByteArray that contains a zlib compressed data stream that is a serialized (pickled) Python object. That way Python objects can be send around.
For an example see examples/lib/network_example.py or examples/server/network_example.py
base/network.py
This is a higher level wrapper around ExtendedTcpSocket from lib/network.py. It introduces Channels (an Enum see C in constants.py) that one can subcribe to and unsubscribe from. Messages (Python objects) are a dictionary with keys: channel (Channel), action (another Enum, see M in constants.py) and the message content (any Python object).
The idea is that everything can connect to a Channels received signal and then gets notified of all messages in that channel and get decide on what to do based on the action (or message type) and the message content.
For an example see examples/server/network_process_example.py or server/network_chat_example.py.
The local network client is a member of the base/network.py modul.
server/server_manager.py
The ServerManager accepts new NetworkClients and handles messages on the server side.
General
- There is always a single local server. It can be either configured to only accept connection from the local device or from everywhere. It's used for local single player games as well as for locally hosted multiplayer games.
- There is always one single local networkclient, that connects to the server (either local or remote) to play a game. When it connects to a server it should either send its unique ID (in case it was connected and lost the connection) or it should get a unique ID from the server, which it then should remember.
- The client does not know everything about the game, only what it needs to know. The flow should ideally be that the client sends a request to the server (player wants to do X), the server either rejects the request or accepts it and sends an update back to the client and to all other clients. The clients then react to the update in states.
- Communication within the server and the client is via signals and slots from Qt, objects should be derived from QObject.
- The server and the client live in different Python processes. At the beginning the client starts a local server in a process, when it ends, it will signal the local server to shut itself down too and will wait for it to finish too.
- The scenario editor does not need to go through all this because one can only edit scenarios locally. It directly works on the data structure containing all informations, which is a ServerScenario.