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/game2.git
cd valley-blocks/client
npm install && npm run dev # port 4173
What it is
A Monument Valley-inspired Tetris PWA: SRS rotation with wall kicks, 7-bag
randomizer, ghost piece, hold, guideline scoring, five palettes that shift
every two levels, synthesized sound, and a rare steerable 🐍 snake piece.
Solo play works fully offline; sharing the page URL turns it into a private
room for up to 16 players — same pieces for everyone from a shared seed,
race or outlast your friends, round after round.
How it works
No game server. Browsers are
js-libp2p peers: they meet through a
circuit-relay-v2 node (gossipsub peer discovery), upgrade to direct
WebRTC, and speak a room-scoped protocol. The room secret lives in the
URL fragment (#…); the protocol id only ever carries a
one-way HKDF of it.
Everything is end-to-end encrypted. libp2p's noise
layer encrypts every peer pair end-to-end — even while frames still ride
the relay, it only routes opaque ciphertext. Room membership is proved
pairwise with a sealed AES-256-GCM hello keyed from the room secret and
bound to both authenticated peer ids (client/src/net/,
shared with neon-grid);
TURN fallback still can't read anything.
One peer referees. The host deals seats and seeds,
judges round outcomes, and hands a snapshot to late joiners (they
spectate, then play the next round). Host conflicts resolve by a shared
precedence rule — an active round outranks an idle claim, a joined player
outranks a parked tab, ties break to lowest peer id — and if the host
vanishes mid-round, the round voids and the lowest surviving id takes
over. Boards themselves are simulated locally — every player broadcasts
their own compact board state, so your controls never wait on the
network.
The site is plain static files. The game and this repo
page are served with no backend anywhere — deploying is replacing a
folder.
Honest guarantees & limits
Guaranteed: no accounts, no analytics, no database, no
third-party requests. Room contents are end-to-end encrypted; the relay
routes opaque ciphertext and sees connection metadata only (peer ids, IP
addresses, traffic volume — as any relay must; room ids never leave the
encrypted channel). Scores and history stay in your browser.
Not guaranteed: the host referees, and each player reports
their own board — a modified client could lie about its board. Play with
friends, not strangers with prize money. Rooms are capped at 16 and a full
mesh gets heavy past ~12 players on phones. Anyone with the room link is in
the room — treat links like invitations.
Layout
client/src/game2/net/ libp2p layer (bootstrap, node, peers, room crypto, TURN) — shared with neon-grid
client/src/game2/game/ the game: core/ render/ input/ ui/ audio/ storage/ + frames.cljs (wire) + party.cljs (referee)
client/src/game2/main.cljs room secret → create-net → party → app
client/test/ golden vectors: wire bytes, referee rules, the board sim
site/ this page · deploy/publish-repo.sh builds the git mirror
valleyblocks
un tetris senin cu camere p2p fără server — pagina asta e și repo-ul git.
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/game2.git
cd valley-blocks/client
npm install && npm run dev # port 4173
Ce este
Un PWA de Tetris inspirat de Monument Valley: rotație SRS cu wall kicks,
randomizer 7-bag, piesă-fantomă, rezervă, punctaj după guideline, cinci palete
care se schimbă la fiecare două niveluri, sunet sintetizat și o rară piesă-🐍
șarpe pe care o poți cârmi. Jocul solo merge complet offline; trimițând URL-ul
paginii o transformi într-o cameră privată pentru până la 16 jucători —
aceleași piese pentru toți dintr-un seed comun, întrece-ți sau rezistă mai
mult decât prietenii, rundă după rundă.
Cum funcționează
Fără server de joc. Browserele sunt peers
js-libp2p: se întâlnesc printr-un nod
circuit-relay-v2 (descoperire prin gossipsub), trec pe WebRTC direct și
vorbesc un protocol legat de cameră. Secretul camerei stă în fragmentul
URL-ului (#…); id-ul de protocol poartă doar un HKDF
ireversibil al lui.
Totul e criptat cap-la-cap. Stratul noise al lui libp2p
criptează fiecare pereche de peers de la un capăt la altul — chiar și cât
timp cadrele mai trec prin releu, acesta rutează doar text cifrat opac.
Apartenența la cameră se dovedește pereche cu pereche, cu un hello sigilat
AES-256-GCM derivat din secretul camerei și legat de ambele peer id-uri
autentificate (client/src/net/, împărțit cu
neon-grid); nici fallback-ul
TURN nu poate citi nimic.
Un peer arbitrează. Gazda împarte locurile și seed-urile,
judecă deznodământul rundelor și dă un snapshot celor care intră târziu
(privesc, apoi joacă runda următoare). Conflictele de gazdă se rezolvă
printr-o regulă de precedență comună — o rundă activă bate o pretenție
inactivă, un jucător intrat bate un tab parcat, egalitățile merg la cel
mai mic peer id — iar dacă gazda dispare în mijlocul rundei, runda se
anulează și preia cel mai mic id supraviețuitor. Tablele în sine se
simulează local — fiecare jucător își difuzează propria stare compactă a
tablei, așa că comenzile tale nu așteaptă niciodată rețeaua.
Situl e doar fișiere statice. Jocul și pagina asta de
repo sunt servite fără niciun backend nicăieri — deploy-ul înseamnă să
înlocuiești un director.
Garanții și limite, pe bune
Garantat: fără conturi, fără analytics, fără bază de
date, fără cereri către terți. Conținutul camerelor e criptat cap-la-cap;
releul rutează text cifrat opac și vede doar metadate de conexiune (peer
id-uri, adrese IP, volum de trafic — ca orice releu; id-urile camerelor nu
părăsesc niciodată canalul criptat). Scorurile și istoricul rămân în
browserul tău.
Negarantat: gazda arbitrează, iar fiecare jucător își
raportează singur tabla — un client modificat ar putea minți despre ea.
Joacă cu prieteni, nu cu străini pe bani. Camerele sunt plafonate la 16, iar
un mesh complet devine greu peste ~12 jucători pe telefoane. Oricine are
linkul camerei e în cameră — tratează linkurile ca pe niște invitații.
Structura
client/src/game2/net/ stratul libp2p (bootstrap, node, peers, cripto de cameră, TURN) — împărțit cu neon-grid
client/src/game2/game/ jocul: core/ render/ input/ ui/ audio/ storage/ + frames.cljs (protocol) + party.cljs (arbitru)
client/src/game2/main.cljs secretul camerei → create-net → party → app
client/test/ vectori de referință: octeții de pe fir, regulile arbitrului, simularea tablei
site/ pagina asta · deploy/publish-repo.sh construiește oglinda git
valleyblocks
derűs tetris szerver nélküli p2p szobákkal — ez az oldal egyben a git repó is.
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/game2.git
cd valley-blocks/client
npm install && npm run dev # port 4173
Mi ez
Monument Valley ihlette Tetris PWA: SRS-forgatás wall kickekkel, 7-bag
randomizer, szellemelem, tartalék, guideline-pontozás, öt paletta, amely két
szintenként vált, szintetizált hang, és egy ritka, kormányozható 🐍
kígyóelem. A szólójáték teljesen offline is megy; az oldal URL-jét megosztva
privát szobává válik akár 16 játékosnak — közös seedből mindenki ugyanazokat
az elemeket kapja, versenyezz vagy bírd tovább a barátaidnál, körről körre.
Hogyan működik
Nincs játékszerver. A böngészők
js-libp2p peerek: egy circuit-relay-v2
node-on át találkoznak (gossipsub peer-felfedezés), közvetlen WebRTC-re
váltanak, és szoba-hatókörű protokollt beszélnek. A szoba titka az URL
fragmentben él (#…); a protokoll-id csak egy egyirányú
HKDF-jét hordozza.
Minden végponttól végpontig titkosított. A libp2p
noise-rétege minden peer-párt végponttól végpontig titkosít — amíg a
keretek még a relén mennek át, az is csak átlátszatlan titkosított
szöveget továbbít. A szobatagságot páronként a szoba titkából
származtatott, mindkét hitelesített peer-id-hoz kötött, lepecsételt
AES-256-GCM hello bizonyítja (client/src/net/, közös a
neon-griddel); a TURN
tartalék sem tud elolvasni semmit.
Az egyik peer a bíró. A házigazda osztja a helyeket és
a seedeket, megítéli a körök kimenetelét, és pillanatképet ad a későn
érkezőknek (ők néznek, aztán a következő körben játszanak). A
házigazda-vitákat közös elsőbbségi szabály dönti el — az aktív kör üti a
tétlen igényt, a belépett játékos üti a parkoló fület, döntetlennél a
legkisebb peer id nyer —, és ha a házigazda kör közben tűnik el, a kör
érvénytelen, és a legkisebb megmaradt id veszi át. Maguk a táblák
helyben szimulálódnak — minden játékos a saját kompakt táblaállapotát
sugározza, így az irányításod soha nem vár a hálózatra.
Az oldal sima statikus fájl. A játékot és ezt a
repó-oldalt sehol semmilyen backend nem szolgálja ki — a telepítés egy
mappa lecserélése.
Garanciák és korlátok, őszintén
Garantált: se fiók, se analitika, se adatbázis, se
harmadik félhez menő kérés. A szobák tartalma végponttól végpontig
titkosított; a relé átlátszatlan titkosított szöveget továbbít, és csak
kapcsolati metaadatokat lát (peer id-k, IP-címek, forgalom mennyisége —
ahogy minden relének muszáj; a szoba-id-k soha nem hagyják el a titkosított
csatornát). A pontszámok és az előzmények a böngésződben maradnak.
Nem garantált: a házigazda bíráskodik, és minden játékos
maga jelenti a tábláját — egy módosított kliens hazudhat róla. Barátokkal
játssz, ne pénzdíjas idegenekkel. A szobák plafonja 16 fő, és a teljes mesh
~12 játékos fölött telefonon nehézzé válik. Bárki, akinél ott a szoba
linkje, bent van a szobában — kezeld a linkeket meghívóként.
Felépítés
client/src/game2/net/ libp2p réteg (bootstrap, node, peers, szoba-kripto, TURN) — közös a neon-griddel
client/src/game2/game/ a játék: core/ render/ input/ ui/ audio/ storage/ + frames.cljs (protokoll) + party.cljs (bíró)
client/src/game2/main.cljs szoba-titok → create-net → party → app
client/test/ referenciavektorok: a vonalon menő bájtok, a bíró szabályai, a tábla szimulációja
site/ ez az oldal · deploy/publish-repo.sh építi a git tükröt