Skip to main content

Lightweight Python library for multiplayer game networking over TCP

Project description

netio-game

A lightweight Python library for multiplayer game networking. It provides a custom binary wire format, decorator-based RPC routing, and server-authoritative object synchronization over TCP.

Features

  • Binary serialization — compact encoding for primitives, tuples, lists, and typed objects
  • RPC routing@request, @response, and @event handlers with optional datatype parsing
  • Object sync — server creates, updates, and deletes Serializable objects on connected clients
  • Per-player visibility — override validate() on synced objects to control who sees what

Requirements

  • Python 3.10+

Installation

From PyPI:

pip install netio-game

From source (development):

git clone <your-repo-url>
cd netio-game
pip install -e .
from netio_game import Client, Host, ServerRouter, ClientRouter

Quick start

Install the package, then run the examples from the repo root:

pip install -e .

Terminal 1 — server:

python examples/server.py

Terminal 2 — client:

python examples/client.py

Expected client output:

[client] connected, waiting for handshake...
[client] joined as PlayerData <('127.0.0.1', ...)>
[client] response: pong to 127.0.0.1
[client] done

Core concepts

Host and Client

Class Role
Host Listens for connections, runs the game manager, syncs objects
Client Connects to a host, receives synced objects, sends messages

Both use background threads for I/O. Call .start() after construction.

Message types

MessageType Direction Purpose
CONNECT Client → Server Initial handshake
REQUEST Client → Server Ask the server to run a route handler
RESPONSE Server → Client Reply to a request
EVENT Either way Fire-and-forget notification
CREATE Server → Client Spawn a synced object
SYNCHRONIZE Server → Client Push field updates
DELETE Server → Client Remove a synced object
ERROR Either way Report an error

Routers

Handlers are registered with decorators on ServerRouter (server) or ClientRouter (client):

from netio_game import ServerRouter, ClientRouter
from netio_game.serialization.routing import MessageType

server_router = ServerRouter()

@server_router.request("ping")
def handle_ping(player, _data):
    return (f"pong to {player.address[0]}",)

@server_router.event("chat", datatype=tuple[str])
def handle_chat(player, data):
    print(player, data[0])
client_router = ClientRouter()

@client_router.response("ping", datatype=tuple[str])
def on_pong(data):
    print(data[0])

# after client.start() and handshake:
client.send_message(MessageType.REQUEST, "ping", ())
client.send_message(MessageType.EVENT, "chat", ("hello",))

Important: If a handler receives payload data, pass datatype= to the decorator (e.g. tuple[str]). Without it, the parsed argument is None.

Server handlers receive (player_data, data). Client handlers receive (data) only.

Serializable objects

Synced game state inherits from Serializable. Fields must use Annotated with SerializeField():

from typing import Annotated
from netio_game import Serializable, SerializeField

class Bullet(Serializable):
    x: Annotated[float, SerializeField()]
    y: Annotated[float, SerializeField()]

    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

On the server, register objects with the sync system:

bullet = Bullet(10.0, 20.0)
host.create_object(bullet)   # sends CREATE to clients
bullet.x = 15.0
host.synchronize()           # pushes deltas
host.delete_object(bullet)   # sends DELETE

Override lifecycle hooks on the client:

def client_on_create(self): ...
def client_on_update(self): ...
def client_on_destroy(self): ...

Override validate(player_data) -> bool to hide objects from specific players.

Player data

Subclass PlayerData for per-connection state. The built-in PlayerData does not serialize address — define your own type if the client needs it (see examples/shared.py):

from typing import Annotated
from netio_game import PlayerData, SerializeField

class GamePlayer(PlayerData):
    address: Annotated[tuple[str, int], SerializeField()]

Pass player_data_type= / pdata_type= to Host and Client respectively.

Publishing to PyPI

pip install build twine
python -m build
twine check dist/*
twine upload dist/*

Project layout

netio-game/
├── client.py              # Client connection and message loop
├── server.py              # Host, GameManager, connection handling
├── router.py              # Decorator-based route handlers
├── datatypes.py           # PlayerData, ConnectionData
├── serialization/
│   ├── serializer.py      # Serializable base class
│   ├── routing.py         # MessageType, Reader, Writer
│   └── io/io.py           # Binary encode/decode
├── util/                  # GenericType, LazyRef helpers
└── examples/              # Runnable server/client demo

Logging

The library writes debug output to network.log and the server also appends to log.txt during development. Both are listed in .gitignore.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

netio_game-0.1.0.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

netio_game-0.1.0-py3-none-any.whl (20.6 kB view details)

Uploaded Python 3

File details

Details for the file netio_game-0.1.0.tar.gz.

File metadata

  • Download URL: netio_game-0.1.0.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for netio_game-0.1.0.tar.gz
Algorithm Hash digest
SHA256 59b1817241f825864d4556f99514df31bd22504d1be1385ee53a2b3a1c47671a
MD5 fcea7647a0cf455ed0507881175e60b8
BLAKE2b-256 61ebb8160ad410315cf1d5bd770eefbf58d5151d7c7c254162b503ee5943c732

See more details on using hashes here.

File details

Details for the file netio_game-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: netio_game-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for netio_game-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b6b8a1e0240777632d38cf547716799187bbc6c536083f1a7b8a3344013c0cb
MD5 dd71bc5d68ca22f089190fe27370b545
BLAKE2b-256 89a1f9888fe246b2165e44fa55b2308dc41f8800d2e861e33874877e4f6305e0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page