STYLY NetSync Server - Multiplayer framework for Location-Based Entertainment VR/MR experiences
Project description
Prepare develop environment
Option A: Use Dev Container (Recommended)
Prerequisites
- VS Code, Docker
- Dev Container extension
Open Dev Container
Click the >< icon in the bottom-left corner of the window.
(Or press Cmd + Shift + P) and select Dev Containers: Reopen in Container.
Option B:
Prerequisites
- Python >=3.11
- uv
Install styly-netsync-server in development mode
pip install -e .
Usage — STYLY NetSync server & CLIs
When you install the package with pip install -e . (editable / development mode), changes to the package's Python source files in your working tree are reflected immediately when you run the commands below — you don't need to reinstall.
# Start STYLY NetSync Server
styly-netsync-server
# Simulate 50 clients
styly-netsync-simulator --clients 50
# Custom server and room
styly-netsync-simulator --server tcp://localhost --room my_room --clients 50
Wire protocol compatibility
- Current transform wire protocol is
protocolVersion = 4. - Transform messages use
MSG_CLIENT_POSE(11) andMSG_ROOM_POSE(12) with the compact V4 pose body. - v4 vs. v3:
xrOriginDeltacarries a Y component as a 4thint16(dx, dy, dz, dyaw= 8 bytes vs. v3's 6), so receivers can reconstruct the sender's rig-Y motion (e.g. elevators). - Legacy transform protocols (v2/v3) and JSON transform fallback are not supported.
- Deploy Unity and Python updates together when changing transform protocol behavior.
- Protocol v4 position quantization ranges:
- Absolute (
headPosAbsonly): signedint24at0.01 mper unit, per-axis range[-83,886.08 m, 83,886.07 m]. - XROrigin locomotion delta (
xrOriginDelta, 4×int16:dx, dy, dz, dyaw):0.01 mper unit for translation,0.1°for yaw. Receivers reconstructphysicalPos = invDeltaRot * (headPos − deltaPos); it is not on the wire as a separate absolute field. - Head-relative (
right/left/virtual): signedint16at0.005 mper unit, per-axis range[-163.84 m, 163.835 m].
- Absolute (
- These are encoding limits, not a hard world-size cap. Worlds can be larger, but encoded axis values are clamped if they exceed the representable range.
Coordinate Range Expansion Options (Design Notes)
The following options summarize trade-offs when expanding absolute-position range.
Assumed baseline (protocolVersion=4):
- Client pose body with
Physical+Head+Right+Leftvalid andvirtualCount=0:46 bytes(matchestest_client_body_size_with_full_pose_no_virtuals). - Room per-client entry (
clientNo + poseTime + clientBody):56 bytes.
| Option | Absolute Position Encoding | Per-axis Range | Client Body Delta | Room Per-client Delta |
|---|---|---|---|---|
| A. Coarser scale (current integer width) | int24 @ 0.02m |
[-167,772.16m, 167,772.14m] |
+0B (46 -> 46) |
+0B (56 -> 56) |
| B. Cell + local | cell(i16, 256m) + local(int24 @ 0.01m) |
[-8,472,494.08m, 8,472,238.07m] |
+6B (46 -> 52, +13.0%) |
+6B (56 -> 62, +10.7%) |
| C. Cell + local (large cell) | cell(i16, 1024m) + local(int24 @ 0.01m) |
[-33,638,318.08m, 33,637,294.07m] |
+6B (46 -> 52, +13.0%) |
+6B (56 -> 62, +10.7%) |
Notes:
- Only
headPosAbsis on the wire as an absolute field;physicalPosis reconstructed fromheadPosAbs + xrOriginDelta. Option B/C deltas therefore apply toheadPosAbsonly. - Option B/C can reduce average overhead if
cellis transmitted only when changed, but that requires extra state and flags in the wire format.
Configuration
The server uses TOML configuration files. Default values are bundled in src/styly_netsync/default.toml.
To customize settings:
-
Get the default config file:
- From local clone:
cp src/styly_netsync/default.toml my-config.toml - Or download from GitHub: default.toml
- From local clone:
-
Edit
my-config.tomland keep only the settings you want to change (delete the rest) -
Run the server with your config file:
styly-netsync-server --config my-config.toml
Configuration priority: CLI arguments > user config > default config
Example minimal config:
# Only override what you need
server_name = "My-Custom-Server"
transform_broadcast_rate = 30 # 30Hz instead of default 10Hz
Logging
File output: add --log-dir DIR to write JSON lines to DIR/netsync-server.log (DEBUG level).
# output logs at ./logs directory
styly-netsync-simulator --log-dir logs
Console output: human-friendly text by default. Use --log-json-console for JSON and --log-level-console LEVEL to change the level.
Rotation & retention: default is 10 MB or 7 days, keeping the newest 20 files. Override with --log-rotation / --log-retention (loguru syntax like "10 MB", "1 day", "keep 5 files").
Bridging: stdlib logging is routed to loguru automatically.
REST bridge
The server launches an embedded FastAPI application that exposes REST endpoints for managing Network Variables. Default port: 8800 (override with --rest-api-port CLI argument or rest_api_port in config file).
Client variables
- Endpoint:
POST /v1/rooms/{roomId}/devices/{deviceId}/client-variables - Payload body:
{
"variables": {
"name": "Jack",
"lang": "EN"
}
}
- Constraints:
- Variable names: 1–64 characters
- Values: up to 1024 characters
- Total variables per client: 20 (additional keys return HTTP 409)
- Behavior:
- If a device has not connected yet, the values are queued in an in-memory preseed store and automatically applied once the server assigns a
clientNo. - If the device is already connected, the variables are sent immediately through the existing ZeroMQ pathway.
- If a device has not connected yet, the values are queued in an in-memory preseed store and automatically applied once the server assigns a
- Example:
curl -sS -X POST "http://127.0.0.1:8800/v1/rooms/default_room/devices/00000000-0000-0000-0000-000000000000/client-variables" \
-H "Content-Type: application/json" \
-d '{"variables":{"name":"Jack","lang":"EN"}}'
The response includes the current mapping status (clientNo or null) and whether each key was "applied" or "queued".
-
Read endpoints:
-
GET /v1/rooms/{roomId}/devices/{deviceId}/client-variables— returns all client variables for the device.{"clientNo": 7, "variables": {"name": "Jack", "lang": "EN"}}
If the device has no
clientNomapping yet, returns{"clientNo": null, "variables": {}}. -
GET /v1/rooms/{roomId}/devices/{deviceId}/client-variables/{name}— returns a single variable.{"clientNo": 7, "value": "Jack"}
Returns
404if the device is unmapped or the variable is not set.
-
-
Example:
curl -sS "http://127.0.0.1:8800/v1/rooms/default_room/devices/00000000-0000-0000-0000-000000000000/client-variables" curl -sS "http://127.0.0.1:8800/v1/rooms/default_room/devices/00000000-0000-0000-0000-000000000000/client-variables/name"
Global variables
- Endpoint:
POST /v1/rooms/{roomId}/global-variables - Payload body:
{
"variables": {
"score": "42",
"stage": "lobby"
}
}
- Constraints:
- Variable names: 1–64 characters
- Values: up to 1024 characters
- Total global variables per room: 100 (additional keys return HTTP 409)
- Behavior:
- If the bridge client for the room is connected, variables are applied immediately via
set_global_variable. - If not yet connected, variables are queued and automatically flushed once the bridge connects. Successfully applied variables are removed from the queue; failed variables are re-queued for the next flush cycle.
- If the bridge client for the room is connected, variables are applied immediately via
- Example:
curl -sS -X POST "http://127.0.0.1:8800/v1/rooms/default_room/global-variables" \
-H "Content-Type: application/json" \
-d '{"variables":{"score":"42","stage":"lobby"}}'
The response includes the room ID and whether each key was "applied", "queued", or "failed".
-
Read endpoints:
-
GET /v1/rooms/{roomId}/global-variables— returns all global variables for the room.{"variables": {"score": "42", "stage": "lobby"}}
-
GET /v1/rooms/{roomId}/global-variables/{name}— returns a single variable.{"value": "42"}
Returns
404if the variable is not set.
-
-
Example:
curl -sS "http://127.0.0.1:8800/v1/rooms/default_room/global-variables" curl -sS "http://127.0.0.1:8800/v1/rooms/default_room/global-variables/score"
Read consistency
GET endpoints return a snapshot of the REST bridge's in-process cache, which is populated by PUB-SUB broadcasts from the server. The first request to a room lazily creates a bridge and may return an empty snapshot until the initial broadcasts arrive — retry after a short delay if needed.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file styly_netsync_server-0.11.0.tar.gz.
File metadata
- Download URL: styly_netsync_server-0.11.0.tar.gz
- Upload date:
- Size: 126.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
112998bd309ee1aed6df15e8277d7da90b40605041319f0172c6bfee7b8078ea
|
|
| MD5 |
409f3075547307337e87515dd7280621
|
|
| BLAKE2b-256 |
2d81ca2a7e982dc20638be1d8e76a2a6bd187763f91d90cc4a21a3441a1c4ff2
|
Provenance
The following attestation bundles were made for styly_netsync_server-0.11.0.tar.gz:
Publisher:
publish-to-pypi.yml on styly-dev/STYLY-NetSync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
styly_netsync_server-0.11.0.tar.gz -
Subject digest:
112998bd309ee1aed6df15e8277d7da90b40605041319f0172c6bfee7b8078ea - Sigstore transparency entry: 1405683336
- Sigstore integration time:
-
Permalink:
styly-dev/STYLY-NetSync@01cba06cebabdef6dca2a5680033732b070c328b -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/styly-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@01cba06cebabdef6dca2a5680033732b070c328b -
Trigger Event:
release
-
Statement type:
File details
Details for the file styly_netsync_server-0.11.0-py3-none-any.whl.
File metadata
- Download URL: styly_netsync_server-0.11.0-py3-none-any.whl
- Upload date:
- Size: 94.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b0d3b840e7149715b20a57411c060f48d9f7ca43831d9a7714b5ac02849c2ca
|
|
| MD5 |
c0556ff1a636191e8f8326d3aede2305
|
|
| BLAKE2b-256 |
73ee4eb308941ffeac959f7d21bcc439dd8d983316799981e5830412caee963b
|
Provenance
The following attestation bundles were made for styly_netsync_server-0.11.0-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on styly-dev/STYLY-NetSync
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
styly_netsync_server-0.11.0-py3-none-any.whl -
Subject digest:
5b0d3b840e7149715b20a57411c060f48d9f7ca43831d9a7714b5ac02849c2ca - Sigstore transparency entry: 1405683365
- Sigstore integration time:
-
Permalink:
styly-dev/STYLY-NetSync@01cba06cebabdef6dca2a5680033732b070c328b -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/styly-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@01cba06cebabdef6dca2a5680033732b070c328b -
Trigger Event:
release
-
Statement type: