NEONGRID
a serverless p2p light-cycle arena — this page is also the git repo.
Clone
This site serves the repository over git's dumb-HTTP protocol as plain static
files (plain files — there is no git server here, or any server at all):
git clone https://git.ardegazu.ro/game1.git
cd neon-grid
What it is
Tron-style multiplayer for up to 16 riders. Everyone rides a light cycle on a
shared 128×96 grid, leaves a solid trail, and the last rider alive wins the
round; first to 5 rounds takes the match. Installable PWA — works saved to an
iOS home screen, safe-area aware, tap-to-steer on phones.
How it works
- No game server. Browsers are
libp2p peers: they meet through a
circuit-relay-v2 node, discover each other via gossipsub, and upgrade to
direct WebRTC. The room secret lives in the URL fragment (
#…)
and never leaves the browser.
- Everything is end-to-end encrypted. Every peer pair is
noise-encrypted end-to-end (even while frames still cross the relay), and
room membership is proved with an AES-256-GCM sealed hello derived from
the room secret — an undecryptable hello means you're not in the room.
TURN with ephemeral credentials covers the stubborn NATs.
- One peer is the referee. The lowest peer id runs a fixed-rate
authoritative grid simulation and broadcasts ~40-byte tick deltas; everyone
else renders from them. Host loss mid-round voids the round and the next
lowest id takes over; late joiners get a run-length-encoded snapshot and
spectate until the next round.
- Hosting without an origin server. The client is a static
Vite build served as plain files — there is no backend anywhere. This page
you're reading works the same way.
What's in the repo
client/src/game/ — the game
TypeScript, no framework: typed wire protocol, host simulation, canvas
renderer (neon trails, derez, particles), WebAudio bleeps, lobby UI.
client/src/net/ — the p2p layer
A thin js-libp2p assembly: relay bootstrap from
/.well-known/ap2p, a room-scoped protocol with a sealed-hello
membership handshake, reconnection, and the six-method surface the game
consumes. Swap the protocol prefix and it drives any turn/tick game.
deploy/ — the publish pipeline
publish-repo.sh builds this very site: landing page + bare
mirror exploded to loose objects (static file servers and git's dumb-HTTP protocol
agree on "every path must exist"), with an anonymity gate that refuses to
publish identity-bearing bytes.
Run it yourself
cd client && npm install && npm run dev # :4173
# open two tabs on the same #room URL and play yourself
Deploy: npm run build, then publish client/dist/ as
static files anywhere — IPFS, a CDN, a folder behind nginx. It needs nothing but
a libp2p circuit relay it's allowed to talk to (see src/game/config.ts).
Guarantees & limits, honestly
- The relay operator sees connection metadata, opaque room ids, and frame
sizes/timing. Not content, not nicknames, not who won.
- Anyone with the room link can join and play — capability model. The
practical ceiling is ~12 riders (full mesh).
- The host referee is one of the players; a cheating host could lie about
the simulation. Between friends that's the same trust as hosting a LAN
party. Inputs from non-host players can't forge anyone else's moves.
- MIT licensed. Built on WebRTC, WebCrypto and canvas.
NEONGRID
o arenă p2p de motociclete de lumină, fără server — pagina asta e și repo-ul git.
Clonare
Situl servește repository-ul prin protocolul dumb-HTTP al lui git, ca simple
fișiere statice (chiar simple fișiere — nu există aici niciun server git, de fapt
niciun server):
git clone https://git.ardegazu.ro/game1.git
cd neon-grid
Ce este
Multiplayer în stil Tron pentru până la 16 piloți. Fiecare conduce o motocicletă
de lumină pe o grilă comună de 128×96, lasă în urmă un zid solid, iar ultimul rămas
în viață câștigă runda; primul la 5 runde ia meciul. PWA instalabil — merge salvat
pe ecranul de start al unui iPhone, respectă safe-area, se cârmește prin atingere
pe telefon.
Cum funcționează
- Fără server de joc. Browserele sunt peers
libp2p: se întâlnesc printr-un nod
circuit-relay-v2, se descoperă prin gossipsub și trec pe WebRTC direct.
Secretul camerei stă în fragmentul URL-ului (
#…) și nu pleacă
niciodată din browser.
- Totul e criptat cap-la-cap. Fiecare pereche de peers e
criptată noise de la un capăt la altul (chiar și cât timp cadrele mai trec
prin releu), iar apartenența la cameră se dovedește cu un hello sigilat
AES-256-GCM derivat din secretul camerei — un hello care nu se poate
decripta înseamnă că nu ești în cameră. TURN cu credențiale efemere acoperă
NAT-urile încăpățânate.
- Un peer e arbitrul. Cel mai mic peer id rulează simularea
autoritativă a grilei la rată fixă și difuzează delte de ~40 de octeți per
tick; restul doar randează. Dacă gazda pică în mijlocul rundei, runda se
anulează și preia următorul id; cine intră târziu primește un snapshot
comprimat RLE și privește până la runda următoare.
- Găzduire fără server de origine. Clientul e un build Vite
static servit ca simple fișiere — nu există backend nicăieri. Pagina pe care
o citești funcționează la fel.
Ce e în repo
client/src/game/ — jocul
TypeScript, fără framework: protocol de rețea tipat, simulare la gazdă,
renderer pe canvas (dâre de neon, derez, particule), bipuri WebAudio, UI de
lobby.
client/src/net/ — stratul p2p
Un asamblaj subțire de js-libp2p: bootstrap de releu din
/.well-known/ap2p, un protocol per cameră cu handshake de
apartenență prin hello sigilat, reconectare, și cele șase metode pe care le
consumă jocul. Schimbi prefixul de protocol și duce orice joc pe tick-uri.
deploy/ — conducta de publicare
publish-repo.sh construiește chiar situl ăsta: pagină de
prezentare + oglindă bare explodată în loose objects (serverele de fișiere
statice și dumb-HTTP-ul lui git cad de acord că „orice cale trebuie să
existe"), cu o poartă de anonimat care refuză să publice octeți care poartă
identitate.
Rulează-l singur
cd client && npm install && npm run dev # :4173
# deschide două taburi pe același URL #cameră și joacă cu tine însuți
Deploy: npm run build, apoi publică client/dist/ ca
fișiere statice oriunde — IPFS, un CDN, un director în spatele lui nginx. N-are
nevoie decât de un releu libp2p cu care are voie să vorbească (vezi
src/game/config.ts).
Garanții și limite, pe bune
- Operatorul releului vede metadate de conexiune, id-uri opace de cameră și
dimensiuni/ritm de cadre. Nu conținut, nu nickname-uri, nu cine a câștigat.
- Oricine are linkul camerei poate intra și juca — model de capabilitate.
Plafonul practic e ~12 piloți (mesh complet).
- Arbitrul-gazdă e unul dintre jucători; o gazdă care trișează poate minți
despre simulare. Între prieteni e aceeași încredere ca la o petrecere LAN.
Inputurile celorlalți nu pot falsifica mișcările nimănui.
- Licență MIT. Construit pe WebRTC, WebCrypto și canvas.
NEONGRID
szerver nélküli p2p fénymotor-aréna — ez az oldal egyben a git repó is.
Klónozás
Az oldal a repót a git dumb-HTTP protokollján át szolgálja ki, sima statikus
fájlokként (tényleg sima fájlok — nincs itt git szerver, sőt semmilyen szerver):
git clone https://git.ardegazu.ro/game1.git
cd neon-grid
Mi ez
Tron-stílusú többjátékos akár 16 versenyzőnek. Mindenki egy fénymotort vezet
a közös 128×96-os rácson, tömör falat húz maga után, és az utolsó életben maradt
nyeri a kört; aki előbb ér 5 körig, viszi a meccset. Telepíthető PWA — iOS
kezdőképernyőre mentve is megy, safe-area-tudatos, telefonon koppintással
kanyarodsz.
Hogyan működik
- Nincs játékszerver. A böngészők
libp2p peerek: egy circuit-relay-v2 node-on
át találkoznak, gossipsubbal fedezik fel egymást, majd közvetlen WebRTC-re
váltanak. A szoba titka az URL fragmentben él (
#…), és soha
nem hagyja el a böngészőt.
- Minden végponttól végpontig titkosított. Minden peer-pár
noise-titkosított végponttól végpontig (akkor is, amíg a keretek még a
relén mennek át), a szobatagságot pedig a szoba titkából származtatott
AES-256-GCM lepecsételt hello bizonyítja — a megfejthetetlen hello annyit
tesz: nem vagy a szobában. A makacs NAT-okat efemer hitelesítésű TURN
fedi le.
- Az egyik peer a bíró. A legkisebb peer id futtatja a
mérvadó rácsszimulációt fix ütemben, és ~40 bájtos tick-deltákat sugároz;
a többiek ezekből rajzolnak. Ha a házigazda kör közben esik ki, a kör
érvénytelen, és a következő legkisebb id veszi át; a későn érkezők
RLE-tömörített pillanatképet kapnak, és a következő körig nézők.
- Hosztolás origin-szerver nélkül. A kliens statikus Vite
build, sima fájlokként kiszolgálva — nincs sehol backend. Ez az oldal is
pontosan így működik.
Mi van a repóban
client/src/game/ — a játék
TypeScript, framework nélkül: típusos wire-protokoll, hoszt-szimuláció,
canvas renderer (neoncsíkok, derez, részecskék), WebAudio pittyegés,
lobbi UI.
client/src/net/ — a p2p réteg
Vékony js-libp2p összeállítás: relé-bootstrap a
/.well-known/ap2p-ből, szoba-hatókörű protokoll lepecsételt
hello tagsági kézfogással, újracsatlakozás, és az a hat metódus, amit a
játék fogyaszt. Cseréld ki a protokoll-előtagot, és bármilyen tick-alapú
játékot elvisz.
deploy/ — a publikáló futószalag
A publish-repo.sh építi ezt az oldalt: nyitólap + bare tükör
loose objectekre bontva (a statikus fájlszerverek és a git dumb-HTTP-je
egyetértenek abban, hogy „minden útvonalnak léteznie kell"), és egy
anonimitás-kapu, amely nem enged identitáshordozó bájtokat publikálni.
Futtasd magad
cd client && npm install && npm run dev # :4173
# nyiss két fület ugyanarra a #szoba URL-re, és játssz magad ellen
Telepítés: npm run build, aztán tedd ki a
client/dist/-et statikus fájlokként bárhová — IPFS, CDN, egy mappa
nginx mögött. Semmi másra nincs szüksége, csak egy libp2p relére, amivel
beszélhet (lásd src/game/config.ts).
Garanciák és korlátok, őszintén
- A relé üzemeltetője kapcsolati metaadatokat, átlátszatlan szoba-id-kat és
keretméretet/ütemet lát. Tartalmat, beceneveket, győztest nem.
- Bárki, akinél ott a szoba linkje, beléphet és játszhat — capability
modell. A gyakorlati plafon ~12 versenyző (teljes mesh).
- A bíró-házigazda az egyik játékos; egy csaló házigazda hazudhat a
szimulációról. Barátok közt ez ugyanaz a bizalom, mint egy LAN-partin.
A többiek inputjai senki más lépéseit nem hamisíthatják.
- MIT licenc. WebRTC-re, WebCryptóra és canvasra épül.