Mega Pacchetto: come gli sviluppatori di Factorio sono riusciti a risolvere il problema con il multiplayer a 200 giocatori.

Mega Pacchetto: come gli sviluppatori di Factorio sono riusciti a risolvere il problema con il multiplayer a 200 giocatori.
A maggio di quest'anno ho partecipato come giocatore a un evento MMO di KatherineOfSky. Ho notato che quando il numero di giocatori raggiunge una certa soglia, ogni pochi minuti una parte di loro "abbandona". Sfortunatamente per voi (ma non per me), ero uno di quei giocatori che si disconnettevano ogni volta, anche con una buona connessione. L'ho visto come una sfida personale e ho iniziato a cercare le cause del problema. Dopo tre settimane di debug, test e correzioni, l'errore è finalmente stato risolto, ma questo viaggio non è stato affatto semplice.

Le problematiche nei giochi multiplayer sono molto difficili da rintracciare. Di solito si verificano in condizioni di rete molto specifiche e in stati di gioco molto peculiari (in questo caso, con oltre 200 giocatori). E anche quando si riesce a riprodurre il problema, non è possibile debuggare correttamente, perché l'inserimento di punti di controllo ferma il gioco, confonde i timer e di solito porta alla chiusura della connessione a causa della scadenza del timeout. Ma grazie alla tenacia e a un ottimo strumento chiamato clumsy , sono riuscito a capire cosa stava succedendo.

Если вкратце: из-за ошибки и неполной реализации симуляции состояния задержки клиент иногда оказывался в ситуации, когда ему приходится за один такт отправлять сетевой пакет, состоящий из вводимых игроком действий выбора примерно 400 игровых сущностей (мы называем его «мегапакетом»). После этого сервер не только должен правильно получить все эти действия ввода, но и отправить их всем остальным клиентам. Если у тебя 200 клиентов, это быстро становится проблемой. Канал к серверу быстро забивается, что приводит к утере пакетов и каскаду повторно запрошенных пакетов. Откладывание действий ввода затем приводит к тому, что ещё больше клиентов начинает отправлять мегапакеты, и их лавина становится ещё сильнее. Удачливым клиентам удаётся восстановиться, все остальные «отваливаются».

Mega Pacchetto: come gli sviluppatori di Factorio sono riusciti a risolvere il problema con il multiplayer a 200 giocatori.
Il problema era piuttosto fondamentale e ci ho messo due settimane per risolverlo. È abbastanza tecnico, quindi di seguito spiegherò i dettagli tecnici succosi. Ma prima di tutto, è importante sapere che dalla versione 0.17.54, rilasciata il 4 giugno, in condizioni di problemi temporanei di connessione, il multiplayer è diventato più stabile, mentre l'occultamento dei ritardi è molto meno difettoso (meno lag e teletrasporti). Inoltre, ho modificato il modo in cui si occultano i ritardi in combattimento e spero che questo li renda un po' più fluidi.

Mega pacchetto multiplayer — dettagli tecnici

Se spieghiamo in modo semplificato, il multiplayer nel gioco funziona come segue: tutti i client simulano lo stato del gioco, ricevendo e inviando solo gli input dei giocatori (chiamati "Input Actions", Input Actions). Il compito principale del server è quello di trasmettere Input Actions e controllare che tutti i client eseguano le stesse azioni in un turno. Maggiori dettagli possono essere letti nel post FFF-149.

Poiché il server deve prendere decisioni su quali azioni devono essere eseguite, le azioni del giocatore seguono approssimativamente questo percorso: azione del giocatore -> client di gioco -> rete -> server -> rete -> client di gioco. Ciò significa che ogni azione del giocatore viene eseguita solo dopo aver completato un viaggio di andata e ritorno attraverso la rete. Di conseguenza, il gioco sembrerebbe terribilmente lento, quindi quasi subito dopo l'introduzione del multiplayer, è stato implementato un meccanismo per nascondere i ritardi. La mascheratura dei ritardi simula l'input del giocatore senza tenere conto delle azioni degli altri giocatori e delle decisioni del server.

Mega Pacchetto: come gli sviluppatori di Factorio sono riusciti a risolvere il problema con il multiplayer a 200 giocatori.
In Factorio esiste uno stato di gioco Stato di Gioco — è lo stato completo della mappa, del giocatore, delle entità e di tutto il resto. Viene simulato in modo deterministico in tutti i client in base alle azioni ricevute dal server. Lo stato di gioco è sacro e se mai dovesse differire dal server o da qualsiasi altro client, si verifica una desincronizzazione.

Inoltre Stato di Gioco abbiamo uno stato di latenza Stato di Latenza. Esso contiene un piccolo sottoinsieme dello stato principale. Stato di Latenza non è sacro e rappresenta semplicemente un quadro di come apparirà lo stato del gioco in futuro sulla base delle informazioni fornite dal giocatore Input Actions.

Per questo motivo conserviamo una copia di ciò che viene creato Input Actions nella coda dei ritardi.

Mega Pacchetto: come gli sviluppatori di Factorio sono riusciti a risolvere il problema con il multiplayer a 200 giocatori.
Cioè, alla fine del processo sul lato client, la situazione apparirà approssimativamente in questo modo:

  1. Applichiamo Input Actions a tutti i giocatori Stato di Gioco come queste azioni di input sono state ricevute dal server.
  2. Rimuoviamo dalla coda dei ritardi tutti Input Actions, che, secondo i dati del server, sono già stati applicati a Stato di Gioco.
  3. Rimuoviamo Stato di Latenza e lo resettiamo, affinché appaia esattamente come Stato di Gioco.
  4. Applichiamo tutte le azioni dalla coda dei ritardi a Stato di Latenza.
  5. Sulla base dei dati Stato di Gioco e Stato di Latenza renderizziamo il gioco per il giocatore.

Tutto questo si ripete in ogni turno.

Troppo difficile? Non rilassatevi, non è ancora tutto. Per compensare l'affidabilità delle connessioni Internet, abbiamo creato due meccanismi:

  • Turni saltati: quando il server decide che Input Actions saranno eseguiti nel turno del gioco, se non ha ricevuto Input Actions alcun giocatore (ad esempio, a causa di un ritardo aumentato), non aspetterà, ma avviserà quel cliente «non ho considerato i tuoi Input Actions, cercherò di aggiungerli nel prossimo passo». Questo è stato fatto per evitare che l'aggiornamento della mappa venga ritardato per tutti gli altri a causa di problemi di connessione (o di computer) di un singolo giocatore. È importante notare che Input Actions non vengono ignorati, ma semplicemente rimandati.
  • Ritardo del percorso di andata e ritorno: il server cerca di stimare quale sia il ritardo nella trasmissione dei dati di andata e ritorno tra il client e il server per ciascun cliente. Ogni 5 secondi discute con il cliente un nuovo ritardo se necessario (a seconda di come si è comportata la connessione in passato) e aumenta o diminuisce di conseguenza il ritardo della trasmissione dei dati di andata e ritorno.

Questi meccanismi sono piuttosto semplici di per sé, ma quando vengono utilizzati insieme (cosa che accade spesso in caso di problemi di connessione), la logica del codice diventa difficile da gestire e presenta molti casi limite. Inoltre, quando entrano in gioco questi meccanismi, il server e la coda dei ritardi devono implementare correttamente un particolare Input Action chiamata StopMovementInTheNextTick. Questo garantisce che, in caso di problemi di connessione, il personaggio non corra da solo (ad esempio, sotto un treno).

Ora dobbiamo spiegarti come funziona la selezione degli oggetti. Uno dei tipi trasmessi Input Action è il cambiamento dello stato di selezione dell'oggetto. Questo comunica a tutti su quale oggetto il giocatore ha posato il cursore. Come puoi capire, questo è uno degli input più frequenti inviati dai clienti, quindi per risparmiare larghezza di banda abbiamo ottimizzato il processo in modo che occupi il meno spazio possibile. Questo è realizzato in questo modo: per ogni selezione dell'oggetto, invece di memorizzare coordinate assolute e ad alta precisione della mappa, il gioco memorizza uno spostamento relativo a bassa precisione rispetto alla selezione precedente. Questo funziona bene, poiché la selezione tramite mouse avviene di solito molto vicino alla selezione precedente. Da questo derivano due requisiti importanti: Input Actions non si devono mai ignorare e devono essere eseguiti nell'ordine corretto. Questi requisiti sono soddisfatti per Stato di Gioco. Ma poiché il compito Stato di latenza è quello di "sembrare abbastanza buono" per il giocatore, nelle condizioni di latenza non vengono rispettati. Stato di Latenza non considera molti casi limite, relativi al mancato rispetto dei cicli e alle variazioni della latenza di andata e ritorno.

Puoi già indovinare dove sta andando a finire. Finalmente iniziamo a vedere le cause del problema del megapas package. La radice del problema risiede nel fatto che, nella decisione se trasmettere l'azione di modifica della selezione, la logica di selezione delle entità si basa su Stato di Latenza, e questo stato non contiene sempre informazioni corrette. Di conseguenza, il megapas package viene generato all'incirca in questo modo:

  1. Il giocatore ha problemi di connessione.
  2. Intervengono meccanismi di salto dei cicli e regolazione del ritardo di trasmissione andata e ritorno.
  3. La coda di stato dei ritardi non tiene conto di questi meccanismi. Questo porta a situazioni in cui alcune azioni vengono rimosse prematuramente o vengono eseguite nell'ordine sbagliato, il che porta a un comportamento errato. Stato di Latenza.
  4. Il giocatore perde il problema di connessione e si simula fino a 400 cicli per raggiungere il server.
  5. In ogni ciclo viene generata e preparata per l'invio al server una nuova azione di modifica della selezione dell'entità.
  6. Il client invia al server un megapas package con oltre 400 modifiche nella selezione delle entità (anche altre azioni: stato di tiro, movimento, ecc., sono state influenzate da questo problema).
  7. Il server riceve 400 azioni di input. Non potendo saltare nemmeno un'azione di input, ordina a tutti i clienti di eseguire queste azioni e le invia attraverso la rete.

Ironia della sorte, il meccanismo progettato per risparmiare banda, finiva per generare enormi pacchetti di rete.

Abbiamo risolto il problema correggendo tutti i casi limite di aggiornamento e supporto della coda di latenza. Anche se è stato piuttosto lungo, alla fine è valsa la pena implementare tutto correttamente, invece di affidarci a rapidi hack.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster