Megapackage: cumu i sviluppatori di Factorio risolve u prublema cù u multiplayer per 200 ghjucatori

Megapackage: cumu i sviluppatori di Factorio risolve u prublema cù u multiplayer per 200 ghjucatori
In maghju di questu annu aghju participatu cum'è ghjucatore Eventi MMO KatherineOfSky. Aghju nutatu chì quandu u nùmeru di ghjucatori righjunghji un certu nùmmuru, ogni pocu minuti, alcuni di elli "fallu". Per furtuna per voi (ma micca per mè), eru unu di quelli ghjucadori chì anu disconnected ogni volta, ancu cù una bona cunnessione. Aghju pigliatu questu cum'è una sfida persunale è hà cuminciatu à circà e cause di u prublema. Dopu trè settimane di debugging, teste è correzioni, u bug hè statu finalmente riparatu, ma u viaghju ùn era micca cusì faciule.

I prublemi cù i ghjochi multiplayer sò assai difficiuli di seguità. Di solitu accade sottu paràmetri di rete assai specifichi è cundizioni di ghjocu assai specifichi (in questu casu, avè più di 200 ghjucatori). E ancu quandu u prublema pò esse ripruduciutu, ùn pò micca esse debuggatu bè perchè l'inserimentu di breakpoints ferma u ghjocu, cunfundisce i timers, è di solitu provoca a cunnessione à u tempu. Ma grazia à a persistenza è un strumentu maravigliu chjamatu goffu Aghju riesciutu à sapè ciò chì passava.

In breve, per via di un bug è di implementazione incompleta di a simulazione di u statu di latenza, u cliente si trovava qualchì volta in una situazione induve avia da mandà un pacchettu di rete cumpostu da l'azzioni di selezzione di input di u ghjucatore di circa 400 entità di ghjocu in un ciculu di clock. chjamemu questu un "mega-packet"). U servitore ùn deve micca solu riceve tutte queste azzioni di input currettamente, ma ancu mandà à tutti l'altri clienti. Sì avete 200 clienti, questu diventa rapidamente un prublema. U ligame à u servitore diventa rapidamente ingutuatu, purtendu à a perdita di pacchetti è una cascata di pacchetti ri-richiesti. Delaying the input action then causes even more clients to send megapackets, causendu l'avalanche per diventà ancu più grande. I clienti furtunati riescenu à ricuperà; tutti l'altri cascanu.

Megapackage: cumu i sviluppatori di Factorio risolve u prublema cù u multiplayer per 200 ghjucatori
U prublema era abbastanza fundamentale è mi pigliò 2 settimane per riparà. Hè abbastanza tecnicu, cusì spiegheraghju i dettagli tecnichi succulenti quì sottu. Ma prima, avete bisognu di sapè chì da a versione 0.17.54, liberata u 4 di ghjugnu, in fronte di prublemi di cunnessione tempuranee, u multiplayer hè diventatu più stabile, è i ritardi di nasconde sò diventati assai menu buggy (menu slowdown and teleporting). Aghju ancu cambiatu u modu di cummattimentu lag hè oculatu è spergu chì questu renderà un pocu più liscia.

Multiplayer Mega Pack - Dettagli tecnichi

Per esse simplicemente, u multiplayer in un ghjocu funziona cusì: tutti i clienti simulanu u statu di u ghjocu, ricevendu è mandendu solu input di u ghjucatore (chjamati "azzioni di input", Azzioni di input). U compitu principale di u servitore hè di trasferimentu Azzioni di input è cuntrullà chì tutti i clienti facenu e stesse azzioni in u stessu ciclu di clock. Pudete leghje più nantu à questu in u post FFF-149.

Siccomu u servitore deve piglià decisioni nantu à ciò chì l'azzioni da fà, l'azzioni di u ghjucatore si movenu apprussimatamente nantu à sta strada: azzione di u ghjocu -> cliente di ghjocu -> rete -> servitore -> rete -> cliente di ghjocu. Questu significa chì l'azzione di ogni ghjucatore hè realizatu solu dopu avè fattu un viaghju di andata à traversu a reta. Per via di questu, u ghjocu pareva terribilmente lento, cusì quasi subitu dopu l'intruduzione di multiplayer in u ghjocu, un mecanismu hè statu introduttu per ammuccià i ritardi. Oculta u ritardu simula l'input di u ghjucatore senza piglià in contu l'azzioni di l'altri ghjucatori è e decisioni di u servitore.

Megapackage: cumu i sviluppatori di Factorio risolve u prublema cù u multiplayer per 200 ghjucatori
Factory hà un statu di ghjocu Statu di ghjocu hè u statu cumpletu di a carta, ghjucadore, entità è tuttu u restu. Hè simulatu deterministicamente in tutti i clienti basatu annantu à l'azzioni ricevuti da u servitore. U statu di u ghjocu hè sacru, è s'ellu cumencia à differisce da u servitore o qualsiasi altru cliente, allora a desincronizazione si trova.

francu Statu di ghjocu avemu un statu di ritardu Statu di latenza. Contene un picculu subset di u statu di terra. Statu di latenza micca sacru è simpricimenti rapprisenta una stampa di ciò chì u statu di ghjocu sarà cum'è in u futuru basatu nantu à inputs player Azzioni di input.

Per questu scopu, guardamu una copia di u creatu Azzioni di input in a fila di ritardu.

Megapackage: cumu i sviluppatori di Factorio risolve u prublema cù u multiplayer per 200 ghjucatori
Questu hè, à a fine di u prucessu da u latu di u cliente, l'imaghjini pare cusì cusì:

  1. Applicamu Azzioni di input tutti i ghjucatori Statu di ghjocu a manera chì sti azzioni di input sò stati ricevuti da u servitore.
  2. Eliminamu tuttu da a fila di ritardu Azzioni di input, chì, sicondu u servitore, sò digià appiicati Statu di ghjocu.
  3. Elimina Statu di latenza è resettallu cusì pare esattamente u listessu cum'è Statu di ghjocu.
  4. Applicamu tutte l'azzioni da a fila di ritardu à Statu di latenza.
  5. Basatu nantu à dati Statu di ghjocu и Statu di latenza Rendemu u ghjocu à u ghjucatore.

Tuttu chistu hè ripetutu in ogni misura.

Troppu difficiule? Ùn rilassate micca, questu ùn hè micca tuttu. Per cumpensà e cunnessione Internet inaffidabile, avemu creatu dui meccanismi:

  • Ticks mancati: quandu u servitore decide chì Azzioni di input serà eseguitu à u ritmu di u ghjocu, allora s'ellu ùn hà micca ricevutu Azzioni di input qualchì ghjucatore (per esempiu, per via di un ritardu aumentatu), ùn averà micca aspittatu, ma informarà stu cliente "Ùn aghju micca cunsideratu u vostru Azzioni di input, Pruvaraghju di aghjunghje in a prossima barra. Questu hè fattu per chì per via di prublemi cù a cunnessione (o l'urdinatore) di un ghjucatore, l'aghjurnamentu di a mappa ùn rallenta micca per tutti l'altri. Hè da nutà chì Azzioni di input ùn sò micca ignorati, ma simpliciamente messi da parte.
  • Latenza di andata e ritorno completa: U servitore prova di indovinà quale hè a latenza di andata e ritorno trà u cliente è u servitore per ogni cliente. Ogni 5 seconde, negozia una nova latenza cù u cliente, se ne necessariu (basatu nantu à cumu si cumportanu a cunnessione in u passatu), è aumenta o diminuite a latenza di andata in cunseguenza.

Per sè stessu, sti miccanismi sò abbastanza sèmplice, ma quandu sò usati inseme (chì spessu succede cù prublemi di cunnessione), a logica di u codice diventa difficiuli di gestisce è cù assai casi di punta. Inoltre, quandu questi miccanismi entranu in ghjocu, u servitore è a fila di ritardu deve implementà bè u speciale Azzione di input sottu u nome StopMovementInTheNextTick. Grazie à questu, s'ellu ci sò prublemi cù a cunnessione, u caratteru ùn correrà micca solu (per esempiu, davanti à un trenu).

Avà avemu bisognu di spiegà à voi cumu funziona a selezzione di l'entità. Unu di i tipi trasmessi Azzione di input hè un cambiamentu in u statu di selezzione di l'entità. Dice à tutti l'entità chì u ghjucatore passa sopra. Comu pudete imaginà, questa hè una di l'azzioni di input più cumuni mandate da i clienti, cusì per salvà a larghezza di banda, l'avemu ottimizzata per piglià u minimu spaziu pussibule. U modu di travagliu hè chì ogni entità hè selezziunata, invece di almacenà coordenate di mappa assoluta, d'alta precisione, u ghjocu guarda un offset relative di bassa precisione da a selezzione precedente. Questu funziona bè perchè e selezzione di u mouse tendenu à esse assai vicinu à a selezzione precedente. Questu suscite duie esigenze impurtanti: Azzioni di input Ùn deve esse mai saltati è deve esse cumpletu in l'ordine currettu. Queste esigenze sò soddisfatte per Statu di ghjocu. Ma dapoi u compitu Statu di latenza in "avè abbastanza bè" per u ghjucatore, ùn sò micca soddisfatti in u statu di ritardu. Statu di latenza ùn piglia micca in contu parechji casi di punta, assuciatu à saltà i cicli di clock è cambià i ritardi di trasmissione di andata e ritorno.

Pudete digià indovinà induve sta andendu. Infine, cuminciamu à vede i motivi di u prublema di megapack. A radica di u prublema hè chì a logica di selezzione di l'entità si basa Statu di latenza, è questu statu ùn cuntene micca sempre l'infurmazione curretta. Dunque, un megapacket hè generatu qualcosa cum'è questu:

  1. U lettore hà prublemi di cunnessione.
  2. Meccanismi per saltà i cicli di clock è regulà u ritardu di a trasmissione di andata e ritorno entra in ghjocu.
  3. A fila di u statu di ritardu ùn piglia micca questi miccanismi in contu. Questu provoca alcune azzioni per esse sguassate prematuremente o eseguite in l'ordine sbagliatu, risultatu in incorrecte Statu di latenza.
  4. U lettore hà un prublema di cunnessione è, per piglià u servitore, simula à 400 cicli.
  5. À ogni tick, una nova azzione, cambiendu a selezzione di l'entità, hè generata è preparata per mandà à u servitore.
  6. U cliente manda un mega-batch di 400+ cambiamenti di selezzione di entità à u servitore (è cù altre azzioni: stati di sparà, stati di caminari, etc. anu ancu patitu stu prublema).
  7. U servitore riceve 400 azzioni di input. Siccomu ùn hè micca permessu di saltà alcuna azzione di input, urdineghja à tutti i clienti per fà queste azzioni è li manda à traversu a reta.

L'ironia hè chì un mecanismu pensatu per salvà a larghezza di banda hà finitu per creà enormi pacchetti di rete.

Avemu affruntatu stu prublema correggendu tutti i casi di punta di l'aghjurnamentu è u supportu di fila di backlog. Ancu s'ellu ci hà pigliatu un pocu di tempu, à a fine, valeva a pena di ottene u dirittu piuttostu cà di confià in pirate veloci.

Source: www.habr.com

Add a comment