Мегапацк: Како је Фацторио решио проблем са 200 играча за више играча

Мегапацк: Како је Фацторио решио проблем са 200 играча за више играча
У мају ове године учествовао сам као играч у ММО догађаји КатхеринеОфСки. Приметио сам да када број играча достигне одређени број, сваких неколико минута неки од њих „отпадну“. На вашу срећу (али не и на мене), ја сам био један од оних играча који су прекинули везу сваки пут, чак и са добром везом. Ово сам схватио као лични изазов и почео да тражим узроке проблема. После три недеље отклањања грешака, тестирања и поправки, грешка је коначно исправљена, али путовање није било тако лако.

Проблеме са играма за више играча је веома тешко пронаћи. Обично се јављају под врло специфичним мрежним параметрима и врло специфичним условима игре (у овом случају, са више од 200 играча). Чак и када се проблем може репродуковати, он се не може правилно отклонити јер уметање тачака прекида зауставља игру, збуњује тајмере и обично доводи до истека везе. Али захваљујући упорности и дивном алату тзв неспретан Успео сам да сазнам шта се дешава.

Укратко, због грешке и непотпуне имплементације симулације стања кашњења, клијент би се понекад нашао у ситуацији да је морао да пошаље мрежни пакет који се састоји од акција одабира улаза играча од приближно 400 ентитета игре у једном циклусу такта ( ово називамо „мега-пакет“). Сервер тада не само да мора исправно да прими све ове улазне радње, већ и да их пошаље свим другим клијентима. Ако имате 200 клијената, то брзо постаје проблем. Веза са сервером брзо постаје зачепљена, што доводи до губитка пакета и каскаде поново захтеваних пакета. Одлагање радње уноса онда узрокује још више клијената да пошаљу мегапакете, узрокујући да лавина постане још већа. Срећни клијенти успевају да се опораве, сви остали падају.

Мегапацк: Како је Фацторио решио проблем са 200 играча за више играча
Проблем је био прилично фундаменталан и требало ми је 2 недеље да га решим. Прилично је технички, па ћу у наставку објаснити сочне техничке детаље. Али прво, морате да знате да је од верзије 0.17.54, објављене 4. јуна, суочени са привременим проблемима са везом, мултиплаиер постао стабилнији, а кашњења у скривању су постала много мања (мање успоравања и телепортовања). Такође сам променио начин на који је скривено кашњење у борби и надам се да ће то учинити мало глаткијим.

Мега пакет за више играча - Технички детаљи

Једноставније речено, мултиплаиер у игри функционише овако: сви клијенти симулирају стање игре, примају и шаљу само унос играча (који се називају „акције уноса“, Инпут Ацтионс). Главни задатак сервера је пренос Инпут Ацтионс и контролишу да сви клијенти обављају исте радње у истом циклусу такта. Више о овоме можете прочитати у посту ФФФ-149.

Пошто сервер мора да доноси одлуке о томе које радње да изврши, радње играча се крећу отприлике овом путањом: радња играча -> клијент игре -> мрежа -> сервер -> мрежа -> клијент игре. То значи да се радња сваког играча изводи тек након кружног путовања кроз мрежу. Због тога би игра изгледала страшно споро, па је скоро одмах након увођења мултиплаиера у игру уведен механизам за скривање кашњења. Сакривање кашњења симулира унос играча без узимања у обзир радњи других играча и одлука сервера.

Мегапацк: Како је Фацторио решио проблем са 200 играча за више играча
Фацторио има стање игре Стање игре је комплетно стање картице, играча, ентитета и свега осталог. У свим клијентима се детерминистички симулира на основу акција примљених од сервера. Стање игре је свето, и ако икада почне да се разликује од сервера или било ког другог клијента, долази до десинхронизације.

Изузев Стање игре имамо стање кашњења Латенци Стате. Садржи мали подскуп основног стања. Латенци Стате није свето и једноставно представља слику о томе како ће стање игре изгледати у будућности на основу уноса играча Инпут Ацтионс.

У ту сврху чувамо копију креираног Инпут Ацтионс у реду за одлагање.

Мегапацк: Како је Фацторио решио проблем са 200 играча за више играча
То јест, на крају процеса на страни клијента слика изгледа отприлике овако:

  1. Применити Инпут Ацтионс сви играчи да Стање игре начин на који су ове улазне акције примљене од сервера.
  2. Уклањамо све из реда за одлагање Инпут Ацтионс, на које су, према речима сервера, већ примењене Стање игре.
  3. Избриши Латенци Стате и ресетујте га тако да изгледа потпуно исто као Стање игре.
  4. Примењујемо све радње из реда за одлагање до Латенци Стате.
  5. На основу података Стање игре и Латенци Стате Предајемо игру играчу.

Све се то понавља у свакој мери.

Тешко? Не опуштајте се, ово није све. Да бисмо надокнадили непоуздане интернет везе, направили смо два механизма:

  • Пропуштени тикови: када сервер то одлучи Инпут Ацтионс биће извршен у такту игре, онда ако није примио Инпут Ацтионс неки играч (на пример, због повећаног кашњења), он неће чекати, већ ће обавестити овог клијента „Нисам узео у обзир ваше Инпут Ацтионс, покушаћу да их додам у следећој траци.” Ово се ради тако да због проблема са везом (или рачунаром) једног играча, ажурирање мапе не успорава за све остале. Вреди напоменути да Инпут Ацтионс нису занемарени, већ једноставно остављени по страни.
  • Потпуна латенција повратног пута: сервер покушава да погоди колика је латенција повратног пута између клијента и сервера за сваког клијента. Сваких 5 секунди преговара о новом кашњењу са клијентом ако је потребно (засновано на томе како се веза понашала у прошлости) и у складу с тим повећава или смањује кашњење повратног пута.

Сами по себи, ови механизми су прилично једноставни, али када се користе заједно (што се често дешава са проблемима са везом), логиком кода постаје тешко управљати и са много рубних случајева. Додатно, када ови механизми дођу у игру, сервер и ред за кашњење морају правилно имплементирати специјал Инпут Ацтион звао СтопМовементИнТхеНектТицк. Захваљујући томе, ако постоје проблеми са везом, лик неће трчати сам (на пример, испред воза).

Сада морамо да вам објаснимо како функционише избор ентитета. Један од типова који се преносе Инпут Ацтион је промена стања избора ентитета. Свима говори над којим ентитетом играч лебди. Као што можете замислити, ово је једна од најчешћих улазних радњи које шаљу клијенти, тако да смо је оптимизовали да заузме што је могуће мање простора да бисмо уштедели пропусни опсег. Начин на који функционише је да док се бира сваки ентитет, уместо да чува апсолутне, високо прецизне координате мапе, игра чува релативни помак ниске прецизности у односу на претходни избор. Ово добро функционише јер су селекције мишем обично веома блиске претходном избору. Ово поставља два важна захтева: Инпут Ацтионс Никада их не треба прескакати и морају се попунити исправним редоследом. Ови захтеви су испуњени за Стање игре. Али пошто задатак Стање кашњења у "изгледају довољно добро" за играча, нису задовољни у стању кашњења. Латенци Стате не узима у обзир много ивичних случајева, повезано са прескакањем циклуса такта и променом кашњења при преносу.

Већ можете да претпоставите куда ово води. Коначно почињемо да увиђамо разлоге за проблем мегапакета. Корен проблема је у томе што се логика избора ентитета ослања на Латенци Стате, а ово стање не садржи увек тачне информације. Дакле, мегапакет се генерише отприлике овако:

  1. Плејер има проблема са везом.
  2. Механизми за прескакање циклуса такта и регулисање кашњења повратног преноса долазе у игру.
  3. Ред стања кашњења не узима у обзир ове механизме. Ово узрокује да се неке радње прерано уклоне или изведу погрешним редоследом, што доводи до нетачних Латенци Стате.
  4. Плејер има проблем са везом и, да би ухватио корак са сервером, симулира до 400 циклуса.
  5. Приликом сваког тика, нова акција, мењајући избор ентитета, се генерише и припрема за слање на сервер.
  6. Клијент шаље серверу мега-серију од 400+ промена избора ентитета (а са другим радњама: стања снимања, стања ходања, итд. такође пати од овог проблема).
  7. Сервер прима 400 улазних радњи. Пошто није дозвољено прескочити било коју радњу уноса, он наређује свим клијентима да изврше те радње и шаље их широм мреже.

Иронија је у томе што је механизам дизајниран да уштеди пропусни опсег на крају створио огромне мрежне пакете.

Овај проблем смо решили тако што смо поправили све крајње случајеве подршке за ажурирање и заостали ред. Иако је за то требало доста времена, на крају је вредело да то урадите како треба него да се ослањате на брзе хакове.

Извор: ввв.хабр.цом

Додај коментар