togethere.cloud/private_html/disciplines/ping-pong/1v1/node-server
2026-05-22 22:00:05 +02:00
..
src Initial commit - present state of togethere.cloud 2026-05-22 22:00:05 +02:00
.env.example Initial commit - present state of togethere.cloud 2026-05-22 22:00:05 +02:00
ecosystem.config.cjs Initial commit - present state of togethere.cloud 2026-05-22 22:00:05 +02:00
package.json Initial commit - present state of togethere.cloud 2026-05-22 22:00:05 +02:00
README.md Initial commit - present state of togethere.cloud 2026-05-22 22:00:05 +02:00

Ping-Pong 1v1 Node.js Match Server

Ten serwer obsługuje mecze 1v1 przez WebSocket, trzyma stan w Redis (reconnect), zapisuje postęp do MySQL i po zakończeniu meczu wywołuje PHP endpoint do przydziału nagród.

Uruchomienie lokalnie

  1. Wejdź do folderu:
    • public_html/disciplines/ping-pong/1v1/node-server
  2. Zainstaluj zależności:
    • npm install
  3. Skopiuj konfigurację:
    • skopiuj .env.example.env i uzupełnij wartości
  4. Start:
    • npm run start

Uruchomienie produkcyjne

Ten serwer musi działać jako osobny proces Node.js na hoście aplikacji. Samo PHP nie wystarczy.

Minimalne wymagania:

  • Node.js 20+
  • MySQL dostępny pod danymi z .env
  • reverse proxy z https://togethere.cloud/ping-pong-1v1 do ws://127.0.0.1:8088/

Redis jest zalecany, ale nie jest już obowiązkowy dla pojedynczej instancji. Jeśli REDIS_URL jest niedostępny, serwer przełączy się na fallback in-memory dla kolejki i snapshotów reconnect.

Przykład startu przez PM2:

  • cd public_html/disciplines/ping-pong/1v1/node-server
  • npm install
  • pm2 start ecosystem.config.cjs
  • pm2 save

Test po starcie procesu:

  • http://127.0.0.1:8088/health
  • przez domenę: https://togethere.cloud/ping-pong-1v1/health

Jeżeli domena zwraca 503, to najczęściej oznacza to, że Apache/Nginx już próbuje proxy, ale proces Node.js nie działa albo nie nasłuchuje na porcie 8088. Jeżeli /health zwraca ok: true i redisMode: memory, to serwer działa bez Redisa w trybie pojedynczej instancji.

Protokół WebSocket (JSON)

Klient wysyła:

  • {"type":"hello","ticket":"..."}
  • {"type":"queue.join"}
  • {"type":"queue.leave"}
  • {"type":"match.input","seq":123,"move":-1|0|1}

Serwer wysyła:

  • {"type":"hello.ok","userId":1}
  • {"type":"queue.status","status":"searching","queueSize":4}
  • {"type":"queue.status","status":"idle"}
  • {"type":"match.found","matchId":"...","side":"left|right"}
  • {"type":"match.state", ... }
  • {"type":"match.end", ... }

Skalowanie

  • Redis trzyma kolejkę matchmakingu i snapshot stanu meczu.
  • Przy wielu instancjach potrzebujesz sticky sessions (L4/L7) albo wspólnej warstwy routingowej na matchId.

Bezpieczeństwo

Ticket wydaje PHP endpoint /api/matches/ping-pong/1v1/ticket.php (wymaga sesji PHP). Node weryfikuje ticket HMAC (PINGPONG_1V1_SHARED_SECRET).

Po zakończeniu meczu Node robi POST do /api/matches/ping-pong/1v1/ (folder z index.php) i dostaje jobId. Klient może potem odpalić animacje i odpytywać /api/matches/ping-pong/1v1/status.php?jobId=....