Passa al contenuto principale

Lobby e Catalogo

Riassunto in linguaggio semplice. Qui vivono due idee correlate. Una lobby è un party di giocatori che registrano insieme per un unico tentativo, vincolato a un singolo gioco — è il modo in cui funzionano le registrazioni co-op del "gruppo di N". Il catalogo è l'elenco dei giochi che permettiamo davvero alle persone di registrare, più i dettagli tecnici su come catturare ciascuno di essi. I due si incontrano in un punto: una lobby deve scegliere un gioco dal catalogo.

Mappa

Lobby — il party

  • lobbies — una riga per party. Un lobby_code è la chiave di accesso condivisibile e leggibile dalle persone; creator_id è chi l'ha aperta; game_slug (FK verso eligible_games.slug) è il gioco vincolato che ogni membro deve registrare. status ∈ (active [default], closed, expired); max_players è vincolato a 2–16 (default 16); expires_at ne limita la durata. Una lobby ha vita breve.
  • lobby_participants — la membership corrente, con PK composta (lobby_id, user_id) — è ciò che la rende la roster corrente (una riga viva per utente per lobby). Porta con sé joined_at, il loro session_id una volta iniziata la registrazione, e server_recording_started_at. È qui che una lobby si collega alla spina dorsale della registrazione — il session_id di un partecipante è lo stesso id che compare in recording_sessions.
  • lobby_join_events — la cronologia completa di join/leave, mai cancellata, guidata da due trigger su lobby_participants: un join fa l'INSERT di una riga (trg_lobby_join_history_insert, source di default participant_insert); un leave non aggiunge una riga — trg_lobby_join_history_delete fa l'UPDATE del left_at della riga aperta più recente. Quindi è prevalentemente in append: una riga per join, marcata come chiusa al leave.

La regola del gioco vincolato è l'invariante importante: la lobby fissa un gioco, e il trigger di confine-gioco di s3_uploads (vedi Spina dorsale della registrazione) rifiuta qualsiasi upload etichettato per la lobby il cui gioco non corrisponde. La FK game_slug → eligible_games.slug è ON UPDATE CASCADE / ON DELETE RESTRICT: la rinomina di uno slug si propaga nelle lobby, ma un gioco idoneo che fa da base a una lobby non può essere cancellato. Vedi Modalità Lobby per il ciclo di vita completo e la superficie HTTP.

Il catalogo dei giochi

Questo è l'angolo più normalizzato dello schema — quattro tabelle descrivono un gioco a livelli, dal "è consentito" fino a "come catturiamo questo specifico eseguibile".

  • eligible_games — l'allowlist. Identificata da igdb_id (l'id del database IGDB) con uno slug e un display_name. enabled è l'interruttore on/off; tokens è un jsonb di token di corrispondenza usati dal rilevamento della libreria giochi per riconoscere un gioco da un titolo scansionato. È la tabella di cui parlano i documenti del Catalogo Giochi, e il confine rispetto a cui ogni upload viene validato.
  • game_store_ids — un gioco può essere venduto su più store, quindi questa mappa un igdb_id a molte coppie (store, store_id). store è l'unico enum Postgres nello schema: steam | epic | gog | microsoft | riot | rockstar | other. La FK igdb_id → eligible_games fa cascade in cancellazione.
  • game_runtime_profiles — la ricetta di cattura per uno specifico eseguibile (exe_name) di una voce store: quale engine usa, un settings_override, e un jsonb settings_enforcement (le impostazioni che forziamo per una cattura pulita; NOT NULL, default {} = "nessuna imposizione"). La FK game_store_id fa cascade.
  • engine_defaults — il settings_spec di base per engine, così che un profilo di runtime debba specificare solo i delta. L'engine di un profilo è una FK verso qui.
Perché così tante tabelle per "un gioco"?

Perché "un gioco" è genuinamente diverse cose: una voce di catalogo (lo consentiamo?), un prodotto acquistabile (quale store, quale id?), e un processo eseguibile (quale exe, quale engine, quali impostazioni di cattura?). Suddividerle ci permette di aggiungere uno store o un eseguibile senza toccare gli altri — e permette di riutilizzare le regole di cattura su ogni gioco con lo stesso engine.

user_game_library — cosa possiede un giocatore

La libreria giochi di ogni giocatore, scansionata da Playnite sulla sua macchina. La PK surrogata è id; l'unicità è su (user_id, playnite_id)non il collegamento al catalogo, quindi due copie store dello stesso gioco IGDB producono due righe. synced_at guida la re-sincronizzazione con throttling. Ogni riga (25 colonne) porta con sé il provider / provider_game_id da cui proviene, il name, i flag di installazione/uso (is_installed, is_hidden, is_favorite), le statistiche di gioco (playtime_seconds, play_count, last_played_at), platform / install_size_bytes / release_date, metadati ricchi (genres, developers, publishers, cover_image_url, executables — tutti jsonb), e, fondamentalmente, game_registry_igdb_id, una FK di ritorno verso eligible_games.igdb_id che collega un titolo posseduto da un giocatore al nostro catalogo.

È così che rispondiamo a "quali giocatori possiedono giochi che vogliamo registrare?" — facendo il join di user_game_library con eligible_games sull'id IGDB.

Modello di accesso

La RLS è abilitata su tutte e otto le tabelle presenti qui. Le tabelle del catalogo (eligible_games, game_store_ids, game_runtime_profiles, engine_defaults) sono di sola lettura per qualsiasi utente autenticato. lobbies e lobby_participants hanno scope di partecipante; user_game_library ha scope di proprietario; lobby_join_events è riservata al solo service-role (la CRM la legge tramite la service key).


Vedi anche: riferimento completo delle colonne per queste tabelle.